This source file includes following definitions.
- it_char_has_category
- char_can_wrap_before
- char_can_wrap_after
- fill_column_indicator_column
- redisplay_other_windows
- wset_redisplay
- fset_redisplay
- bset_redisplay
- bset_update_mode_line
- wset_update_mode_line
- ATTRIBUTE_FORMAT_PRINTF
- ATTRIBUTE_FORMAT_PRINTF
- window_text_bottom_y
- window_box_width
- window_box_height
- window_box_left_offset
- window_box_right_offset
- window_box_left
- window_box_right
- window_box
- window_box_edges
- line_bottom_y
- DEFUN
- default_line_pixel_height
- string_from_display_spec
- window_hscroll_limited
- reset_box_start_end_flags
- pos_visible_p
- check_char_and_length
- string_pos_nchars_ahead
- string_pos
- c_string_pos
- number_of_chars
- compute_string_pos
- estimate_mode_line_height
- pixel_to_glyph_coords
- x_y_to_hpos_vpos
- frame_to_window_pixel_xy
- get_glyph_string_clip_rects
- get_glyph_string_clip_rect
- get_phys_cursor_geometry
- remember_mouse_glyph
- adjust_window_ends
- hscrolling_current_line_p
- safe_eval_handler
- safe__call
- safe_call
- safe_call1
- safe__call1
- safe_eval
- safe__eval
- safe_call2
- CHECK_IT
- CHECK_WINDOW_END
- init_iterator
- get_narrowed_width
- get_narrowed_len
- get_medium_narrowing_begv
- get_medium_narrowing_zv
- get_nearby_bol_pos
- get_small_narrowing_begv
- get_large_narrowing_begv
- get_large_narrowing_zv
- unwind_narrowed_begv
- start_display
- in_ellipses_for_invisible_text_p
- init_from_display_pos
- init_to_row_start
- init_to_row_end
- handle_stop
- compute_stop_pos
- compute_display_string_pos
- compute_display_string_end
- handle_fontified_prop
- face_at_pos
- handle_face_prop
- underlying_face_id
- face_before_or_after_it_pos
- handle_invisible_prop
- setup_for_ellipsis
- find_display_property
- get_display_property
- display_min_width
- handle_display_prop
- handle_display_spec
- display_prop_end
- handle_single_display_spec
- display_prop_intangible_p
- single_display_spec_string_p
- display_prop_string_p
- string_buffer_position_lim
- string_buffer_position
- handle_composition_prop
- handle_overlay_change
- next_overlay_string
- compare_overlay_entries
- load_overlay_strings
- get_overlay_strings_1
- get_overlay_strings
- push_it
- iterate_out_of_display_property
- restore_face_box_flags
- pop_it
- back_to_previous_line_start
- strings_with_newlines
- forward_to_next_line_start
- back_to_previous_visible_line_start
- reseat_at_previous_visible_line_start
- reseat_at_next_visible_line_start
- reseat
- reseat_1
- reseat_to_string
- lookup_glyphless_char_display
- merge_escape_glyph_face
- merge_glyphless_glyph_face
- forget_escape_and_glyphless_faces
- get_next_display_element
- set_iterator_to_next
- next_element_from_display_vector
- get_visually_first_element
- next_element_from_string
- next_element_from_c_string
- next_element_from_ellipsis
- next_element_from_image
- next_element_from_xwidget
- next_element_from_stretch
- compute_stop_pos_backwards
- handle_stop_backwards
- next_element_from_buffer
- next_element_from_composition
- move_it_in_display_line_to
- move_it_in_display_line
- move_it_to
- move_it_vertically_backward
- move_it_vertically
- move_it_past_eol
- move_it_by_lines
- partial_line_height
- fast_move_it_horizontally
- in_display_vector_p
- window_text_pixel_size
- DEFUN
- format_nargs
- add_to_log
- vadd_to_log
- message_log_maybe_newline
- message_dolog
- message_log_check_duplicate
- message3
- message_to_stderr
- message3_nolog
- message1
- message1_nolog
- message_with_string
- ATTRIBUTE_FORMAT_PRINTF
- message
- update_echo_area
- ensure_echo_area_buffers
- with_echo_area_buffer
- with_echo_area_buffer_unwind_data
- unwind_with_echo_area_buffer
- setup_echo_area_for_printing
- display_echo_area
- display_echo_area_1
- resize_echo_area_exactly
- resize_mini_window_1
- resize_mini_window
- current_message
- current_message_1
- push_message
- restore_message
- pop_message_unwind
- check_message_stack
- clear_message_stack
- truncate_echo_area
- truncate_message_1
- set_message
- set_message_1
- clear_message
- clear_garbaged_frames
- echo_area_display
- window_buffer_changed
- mode_line_update_needed
- window_frozen_p
- format_mode_line_unwind_data
- unwind_format_mode_line
- store_mode_line_noprop_char
- store_mode_line_noprop
- gui_consider_frame_title
- needs_no_redisplay
- prepare_menu_bars
- update_menu_bar
- restore_selected_window
- restore_frame_selected_window
- update_tab_bar
- display_tab_bar
- build_desired_tab_bar_string
- display_tab_bar_line
- tab_bar_height
- redisplay_tab_bar
- tab_bar_item_info
- get_tab_bar_item
- handle_tab_bar_click
- note_tab_bar_highlight
- tty_get_tab_bar_item
- tty_handle_tab_bar_click
- update_tool_bar
- build_desired_tool_bar_string
- display_tool_bar_line
- tool_bar_height
- redisplay_tool_bar
- tool_bar_item_info
- get_tool_bar_item
- handle_tool_bar_click_with_device
- handle_tool_bar_click
- note_tool_bar_highlight
- hscroll_window_tree
- hscroll_windows
- debug_method_add
- text_outside_line_unchanged_p
- redisplay
- overlay_arrow_string_or_property
- overlay_arrow_in_current_buffer_p
- overlay_arrows_changed_p
- update_overlay_arrows
- overlay_arrow_at_row
- check_point_in_composition
- reconsider_clip_changes
- propagate_buffer_redisplay
- redisplay_internal
- unwind_redisplay_preserve_echo_area
- redisplay_preserve_echo_area
- unwind_redisplay
- unwind_display_working_on_window
- mark_window_display_accurate_1
- mark_window_display_accurate
- disp_char_vector
- block_buffer_flips
- unblock_buffer_flips
- buffer_flipping_blocked_p
- redisplay_windows
- redisplay_window_error
- redisplay_window_0
- redisplay_window_1
- update_redisplay_ticks
- set_cursor_from_row
- run_window_scroll_functions
- cursor_row_fully_visible_p
- try_scrolling
- compute_window_start_on_continuation_line
- try_cursor_movement
- set_vertical_scroll_bar
- set_horizontal_scroll_bar
- window_start_acceptable_p
- DEFUN
- redisplay_window
- try_window
- try_window_reusing_current_matrix
- find_last_row_displaying_text
- find_last_unchanged_at_beg_row
- find_first_unchanged_at_end_row
- sync_frame_with_window_matrix_rows
- row_containing_pos
- try_window_id
- dump_glyph_row
- dump_glyph
- dump_glyph_row
- DEFUN
- DEFUN
- DEFUN
- get_overlay_arrow_glyph_row
- insert_left_trunc_glyphs
- row_hash
- compute_line_metrics
- clear_position
- append_space_for_newline
- extend_face_to_end_of_line
- trailing_whitespace_p
- highlight_trailing_whitespace
- row_for_charpos_p
- cursor_row_p
- push_prefix_prop
- get_it_property
- get_line_prefix_it_property
- handle_line_prefix
- unproduce_glyphs
- find_row_edges
- display_count_lines_logically
- display_count_lines_visually
- maybe_produce_line_number
- should_produce_line_number
- row_text_area_empty
- display_line
- DEFUN
- DEFUN
- DEFUN
- display_menu_bar
- deep_copy_glyph_row
- display_tty_menu_item
- redisplay_mode_lines
- display_mode_lines
- display_mode_line
- move_elt_to_front
- safe_set_text_properties
- display_mode_element
- store_mode_line_string
- pint2str
- pint2hrstr
- decode_mode_spec_coding
- percent99
- decode_mode_spec
- count_lines
- display_count_lines
- display_string
- invisible_prop
- DEFUN
- calc_pixel_width_or_height
- get_font_ascent_descent
- dump_glyph_string
- init_glyph_string
- append_glyph_string_lists
- prepend_glyph_string_lists
- append_glyph_string
- get_char_face_and_encoding
- get_glyph_face_and_encoding
- get_char_glyph_code
- fill_composite_glyph_string
- fill_gstring_glyph_string
- fill_glyphless_glyph_string
- fill_glyph_string
- fill_image_glyph_string
- fill_xwidget_glyph_string
- fill_stretch_glyph_string
- get_per_char_metric
- normal_char_ascent_descent
- normal_char_height
- gui_get_glyph_overhangs
- left_overwritten
- left_overwriting
- right_overwritten
- right_overwriting
- set_glyph_string_background_width
- glyph_string_containing_background_width
- compute_overhangs_and_x
- draw_glyphs
- font_for_underline_metrics
- append_glyph
- append_composite_glyph
- take_vertical_position_into_account
- produce_image_glyph
- produce_xwidget_glyph
- append_stretch_glyph
- produce_stretch_glyph
- produce_special_glyphs
- pad_mode_line
- calc_line_height_property
- append_glyphless_glyph
- produce_glyphless_glyph
- gui_produce_glyphs
- gui_write_glyphs
- gui_insert_glyphs
- gui_clear_end_of_line
- get_specified_cursor_type
- set_frame_cursor_types
- get_window_cursor_type
- notice_overwritten_cursor
- gui_fix_overlapping_area
- draw_phys_cursor_glyph
- erase_phys_cursor
- display_and_set_cursor
- update_window_cursor
- update_cursor_in_window_tree
- gui_update_cursor
- gui_clear_cursor
- draw_row_with_mouse_face
- show_mouse_face
- clear_mouse_face
- coords_in_mouse_face_p
- cursor_in_mouse_face_p
- rows_from_pos_range
- mouse_face_from_buffer_pos
- fast_find_string_pos
- mouse_face_from_string_pos
- on_hot_spot_p
- find_hot_spot
- define_frame_cursor1
- note_mode_line_or_margin_highlight
- note_mouse_highlight
- gui_clear_window_mouse_face
- cancel_mouse_face
- expose_area
- expose_line
- expose_overlaps
- phys_cursor_in_rect_p
- gui_draw_vertical_border
- gui_draw_right_divider
- gui_draw_bottom_divider
- expose_window
- expose_window_tree
- expose_frame
- gui_intersect_rectangles
- syms_of_xdisp
- init_xdisp
- show_hourglass
- start_hourglass
- cancel_hourglass
- adjust_glyph_width_for_mouse_face
- get_cursor_offset_for_mouse_face
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433 #include <config.h>
434 #include <stdlib.h>
435 #include <limits.h>
436 #include <math.h>
437
438 #include "lisp.h"
439 #include "atimer.h"
440 #include "composite.h"
441 #include "keyboard.h"
442 #include "sysstdio.h"
443 #include "systime.h"
444 #include "frame.h"
445 #include "window.h"
446 #include "termchar.h"
447 #include "dispextern.h"
448 #include "character.h"
449 #include "category.h"
450 #include "buffer.h"
451 #include "charset.h"
452 #include "indent.h"
453 #include "commands.h"
454 #include "keymap.h"
455 #include "disptab.h"
456 #include "termhooks.h"
457 #include "termopts.h"
458 #include "intervals.h"
459 #include "coding.h"
460 #include "region-cache.h"
461 #include "font.h"
462 #include "fontset.h"
463 #include "blockinput.h"
464 #include "xwidget.h"
465 #ifdef HAVE_WINDOW_SYSTEM
466 #include TERM_HEADER
467 #endif
468
469 #ifndef FRAME_OUTPUT_DATA
470 #define FRAME_OUTPUT_DATA(f) (NULL)
471 #endif
472
473 #define DISP_INFINITY 10000000
474
475
476 static Lisp_Object list_of_error;
477
478 #ifdef HAVE_WINDOW_SYSTEM
479
480
481
482
483 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \
484 (!NILP (Voverflow_newline_into_fringe) \
485 && FRAME_WINDOW_P ((IT)->f) \
486 && ((IT)->bidi_it.paragraph_dir == R2L \
487 ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
488 : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
489 && (IT)->current_x == (IT)->last_visible_x)
490
491 #else
492 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) false
493 #endif
494
495
496
497
498
499 #define IT_DISPLAYING_WHITESPACE(it) \
500 ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
501 || ((STRINGP (it->string) \
502 && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
503 || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
504 || (it->s \
505 && (it->s[IT_BYTEPOS (*it)] == ' ' \
506 || it->s[IT_BYTEPOS (*it)] == '\t')) \
507 || (IT_BYTEPOS (*it) < ZV_BYTE \
508 && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
509 || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))
510
511
512
513 #define NOT_AT_EOL '<'
514 #define NOT_AT_BOL '>'
515 #define LINE_BREAKABLE '|'
516
517 static bool
518 it_char_has_category(struct it *it, int cat)
519 {
520 int ch = 0;
521 if (it->what == IT_CHARACTER)
522 ch = it->c;
523 else if (STRINGP (it->string))
524 ch = SREF (it->string, IT_STRING_BYTEPOS (*it));
525 else if (it->s)
526 ch = it->s[IT_BYTEPOS (*it)];
527 else if (IT_BYTEPOS (*it) < ZV_BYTE)
528 ch = *BYTE_POS_ADDR (IT_BYTEPOS (*it));
529
530 if (ch == 0)
531 return false;
532 else
533 return CHAR_HAS_CATEGORY (ch, cat);
534 }
535
536
537 static bool
538 char_can_wrap_before (struct it *it)
539 {
540 if (!word_wrap_by_category)
541 return !IT_DISPLAYING_WHITESPACE (it);
542
543
544
545
546 int not_at_bol;
547 if (it->glyph_row && it->glyph_row->reversed_p)
548 not_at_bol = NOT_AT_EOL;
549 else
550 not_at_bol = NOT_AT_BOL;
551
552
553 return (!IT_DISPLAYING_WHITESPACE (it)
554
555 && !it_char_has_category (it, not_at_bol));
556 }
557
558
559 static bool
560 char_can_wrap_after (struct it *it)
561 {
562 if (!word_wrap_by_category)
563 return IT_DISPLAYING_WHITESPACE (it);
564
565
566
567
568 int not_at_eol;
569 if (it->glyph_row && it->glyph_row->reversed_p)
570 not_at_eol = NOT_AT_BOL;
571 else
572 not_at_eol = NOT_AT_EOL;
573
574 return (IT_DISPLAYING_WHITESPACE (it)
575
576 || (it_char_has_category (it, LINE_BREAKABLE)
577 && !it_char_has_category (it, not_at_eol)));
578 }
579
580 #undef IT_DISPLAYING_WHITESPACE
581 #undef NOT_AT_EOL
582 #undef NOT_AT_BOL
583 #undef LINE_BREAKABLE
584
585
586
587
588 static int
589 fill_column_indicator_column (struct it *it, int char_width)
590 {
591 if (display_fill_column_indicator
592 && !it->w->pseudo_window_p
593 && it->continuation_lines_width == 0
594 && CHARACTERP (Vdisplay_fill_column_indicator_character))
595 {
596 Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
597 ? BVAR (current_buffer, fill_column)
598 : Vdisplay_fill_column_indicator_column);
599
600
601
602 if (RANGED_FIXNUMP (0, col, INT_MAX))
603 {
604 int icol = XFIXNUM (col);
605 if (!ckd_mul (&icol, icol, char_width)
606 && !ckd_add (&icol, icol, it->lnum_pixel_width))
607 return icol;
608 }
609 }
610 return -1;
611 }
612
613
614
615 bool noninteractive_need_newline;
616
617
618
619 static bool message_log_need_newline;
620
621
622
623
624 static Lisp_Object message_dolog_marker1;
625 static Lisp_Object message_dolog_marker2;
626 static Lisp_Object message_dolog_marker3;
627
628
629
630
631
632
633 static struct text_pos this_line_start_pos;
634
635
636
637
638 static struct text_pos this_line_end_pos;
639
640
641
642 static int this_line_vpos;
643 static int this_line_y;
644 static int this_line_pixel_height;
645
646
647
648
649 static int this_line_start_x;
650
651
652
653
654
655 static struct text_pos this_line_min_pos;
656
657
658
659 static struct buffer *this_line_buffer;
660
661
662
663 static bool overlay_arrow_seen;
664
665
666
667 static Lisp_Object default_invis_vector[3];
668
669
670
671
672
673 Lisp_Object echo_area_window;
674
675
676
677
678 static Lisp_Object Vmessage_stack;
679
680
681
682
683 static bool message_enable_multibyte;
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715 int windows_or_buffers_changed;
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736 int update_mode_lines;
737
738
739
740
741 static bool line_number_displayed;
742
743
744
745
746 Lisp_Object echo_area_buffer[2];
747
748
749
750 static Lisp_Object echo_buffer[2];
751
752
753
754 static Lisp_Object Vwith_echo_area_save_vector;
755
756
757
758
759 static bool display_last_displayed_message_p;
760
761
762
763
764 static bool message_buf_print;
765
766
767
768
769 static bool message_cleared_p;
770
771
772
773
774 #define MAX_SCRATCH_GLYPHS 100
775 static struct glyph_row scratch_glyph_row;
776 static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
777
778
779
780 static int last_height;
781
782
783
784 bool help_echo_showing_p;
785
786
787
788
789
790
791
792 #define TEXT_PROP_DISTANCE_LIMIT 100
793
794
795
796
797
798
799
800
801 #define SAVE_IT(ITCOPY, ITORIG, CACHE) \
802 do { \
803 if (CACHE) \
804 bidi_unshelve_cache (CACHE, true); \
805 ITCOPY = ITORIG; \
806 CACHE = bidi_shelve_cache (); \
807 } while (false)
808
809 #define RESTORE_IT(pITORIG, pITCOPY, CACHE) \
810 do { \
811 if (pITORIG != pITCOPY) \
812 *(pITORIG) = *(pITCOPY); \
813 bidi_unshelve_cache (CACHE, false); \
814 CACHE = NULL; \
815 } while (false)
816
817
818 enum { REDISPLAY_SOME = 2};
819
820 static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
821 struct font *, bool, int *);
822
823 void
824 redisplay_other_windows (void)
825 {
826 if (!windows_or_buffers_changed)
827 windows_or_buffers_changed = REDISPLAY_SOME;
828 }
829
830 void
831 wset_redisplay (struct window *w)
832 {
833
834 if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
835 redisplay_other_windows ();
836 w->redisplay = true;
837 }
838
839 void
840 fset_redisplay (struct frame *f)
841 {
842 redisplay_other_windows ();
843 f->redisplay = true;
844 }
845
846 void
847 bset_redisplay (struct buffer *b)
848 {
849 int count = buffer_window_count (b);
850 if (count > 0)
851 {
852
853 if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
854 redisplay_other_windows ();
855
856
857
858 b->text->redisplay = true;
859 }
860 }
861
862 void
863 bset_update_mode_line (struct buffer *b)
864 {
865 if (!update_mode_lines)
866 update_mode_lines = REDISPLAY_SOME;
867 b->text->redisplay = true;
868 }
869
870 void
871 wset_update_mode_line (struct window *w)
872 {
873 w->update_mode_line = true;
874
875
876
877
878
879
880 wset_redisplay (w);
881 }
882
883 DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
884 Sset_buffer_redisplay, 4, 4, 0,
885 doc:
886 )
887 (Lisp_Object symbol, Lisp_Object newval, Lisp_Object op, Lisp_Object where)
888 {
889 bset_update_mode_line (current_buffer);
890 current_buffer->prevent_redisplay_optimizations_p = true;
891 return Qnil;
892 }
893
894
895
896
897
898 #ifdef GLYPH_DEBUG
899 extern bool trace_redisplay_p EXTERNALLY_VISIBLE;
900 bool trace_redisplay_p;
901 #else
902 enum { trace_redisplay_p = false };
903 #endif
904 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
905 redisplay_trace (char const *fmt, ...)
906 {
907 if (trace_redisplay_p)
908 {
909 va_list ap;
910 va_start (ap, fmt);
911 vprintf (fmt, ap);
912 va_end (ap);
913 }
914 }
915
916 #ifdef DEBUG_TRACE_MOVE
917 extern bool trace_move EXTERNALLY_VISIBLE;
918 bool trace_move;
919 #else
920 enum { trace_move = false };
921 #endif
922 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
923 move_trace (char const *fmt, ...)
924 {
925 if (trace_move)
926 {
927 va_list ap;
928 va_start (ap, fmt);
929 vprintf (fmt, ap);
930 va_end (ap);
931 }
932 }
933
934
935
936 static struct buffer *displayed_buffer;
937
938
939
940 enum prop_handled
941 {
942 HANDLED_NORMALLY,
943 HANDLED_RECOMPUTE_PROPS,
944 HANDLED_OVERLAY_STRING_CONSUMED,
945 HANDLED_RETURN
946 };
947
948
949
950
951 struct props
952 {
953
954 short name;
955
956
957 enum prop_idx idx;
958
959
960
961 enum prop_handled (*handler) (struct it *it);
962 };
963
964 static enum prop_handled handle_face_prop (struct it *);
965 static enum prop_handled handle_invisible_prop (struct it *);
966 static enum prop_handled handle_display_prop (struct it *);
967 static enum prop_handled handle_composition_prop (struct it *);
968 static enum prop_handled handle_overlay_change (struct it *);
969 static enum prop_handled handle_fontified_prop (struct it *);
970
971
972
973 static struct props it_props[] =
974 {
975 {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
976
977
978 {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
979 {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
980 {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
981 {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
982 {0, 0, NULL}
983 };
984
985
986
987 enum move_it_result
988 {
989
990 MOVE_UNDEFINED,
991
992
993 MOVE_POS_MATCH_OR_ZV,
994
995
996 MOVE_X_REACHED,
997
998
999
1000 MOVE_LINE_CONTINUED,
1001
1002
1003
1004 MOVE_LINE_TRUNCATED,
1005
1006
1007 MOVE_NEWLINE_OR_CR
1008 };
1009
1010
1011
1012
1013
1014
1015 #define CLEAR_FACE_CACHE_COUNT 500
1016 static int clear_face_cache_count;
1017
1018
1019
1020 #ifdef HAVE_WINDOW_SYSTEM
1021 #define CLEAR_IMAGE_CACHE_COUNT 101
1022 static int clear_image_cache_count;
1023
1024
1025 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
1026 #endif
1027
1028
1029
1030 bool redisplaying_p;
1031
1032
1033
1034
1035
1036
1037
1038
1039 bool display_working_on_window_p;
1040
1041
1042
1043
1044 Lisp_Object help_echo_string;
1045 Lisp_Object help_echo_window;
1046 Lisp_Object help_echo_object;
1047 ptrdiff_t help_echo_pos;
1048
1049
1050
1051 Lisp_Object previous_help_echo_string;
1052
1053
1054
1055 #ifdef HAVE_WINDOW_SYSTEM
1056
1057
1058 static bool hourglass_shown_p;
1059
1060
1061
1062 static struct atimer *hourglass_atimer;
1063
1064 #endif
1065
1066
1067
1068 #define DEFAULT_HOURGLASS_DELAY 1
1069
1070 #ifdef HAVE_WINDOW_SYSTEM
1071
1072
1073 #define THIN_SPACE_WIDTH 1
1074
1075 #endif
1076
1077
1078
1079 static void setup_for_ellipsis (struct it *, int);
1080 static void set_iterator_to_next (struct it *, bool);
1081 static void mark_window_display_accurate_1 (struct window *, bool);
1082 static bool row_for_charpos_p (struct glyph_row *, ptrdiff_t);
1083 static bool cursor_row_p (struct glyph_row *);
1084 static int redisplay_mode_lines (Lisp_Object, bool);
1085
1086 static void handle_line_prefix (struct it *);
1087
1088 static void handle_stop_backwards (struct it *, ptrdiff_t);
1089 static void unwind_with_echo_area_buffer (Lisp_Object);
1090 static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
1091 static bool current_message_1 (void *, Lisp_Object);
1092 static bool truncate_message_1 (void *, Lisp_Object);
1093 static void set_message (Lisp_Object);
1094 static bool set_message_1 (void *, Lisp_Object);
1095 static bool display_echo_area_1 (void *, Lisp_Object);
1096 static bool resize_mini_window_1 (void *, Lisp_Object);
1097 static void unwind_redisplay (void);
1098 static void extend_face_to_end_of_line (struct it *);
1099 static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
1100 static void push_it (struct it *, struct text_pos *);
1101 static void iterate_out_of_display_property (struct it *);
1102 static void pop_it (struct it *);
1103 static void redisplay_internal (void);
1104 static void echo_area_display (bool);
1105 static void block_buffer_flips (void);
1106 static void unblock_buffer_flips (void);
1107 static void redisplay_windows (Lisp_Object);
1108 static void redisplay_window (Lisp_Object, bool);
1109 static Lisp_Object redisplay_window_error (Lisp_Object);
1110 static Lisp_Object redisplay_window_0 (Lisp_Object);
1111 static Lisp_Object redisplay_window_1 (Lisp_Object);
1112 static bool set_cursor_from_row (struct window *, struct glyph_row *,
1113 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
1114 int, int);
1115 static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
1116 static bool update_menu_bar (struct frame *, bool, bool);
1117 static bool try_window_reusing_current_matrix (struct window *);
1118 static int try_window_id (struct window *);
1119 static void maybe_produce_line_number (struct it *);
1120 static bool should_produce_line_number (struct it *);
1121 static bool display_line (struct it *, int);
1122 static int display_mode_lines (struct window *);
1123 static int display_mode_line (struct window *, enum face_id, Lisp_Object);
1124 static int display_mode_element (struct it *, int, int, int, Lisp_Object,
1125 Lisp_Object, bool);
1126 static int store_mode_line_string (const char *, Lisp_Object, bool, int, int,
1127 Lisp_Object);
1128 static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
1129 static void display_menu_bar (struct window *);
1130 static void display_tab_bar (struct window *);
1131 static void update_tab_bar (struct frame *, bool);
1132 static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t,
1133 ptrdiff_t *);
1134 static void pint2str (register char *, register int, register ptrdiff_t);
1135
1136 static int display_string (const char *, Lisp_Object, Lisp_Object,
1137 ptrdiff_t, ptrdiff_t, struct it *, int, int, int,
1138 int);
1139 static void compute_line_metrics (struct it *);
1140 static bool get_overlay_strings (struct it *, ptrdiff_t);
1141 static bool get_overlay_strings_1 (struct it *, ptrdiff_t, bool);
1142 static void next_overlay_string (struct it *);
1143 static void reseat (struct it *, struct text_pos, bool);
1144 static void reseat_1 (struct it *, struct text_pos, bool);
1145 static bool next_element_from_display_vector (struct it *);
1146 static bool next_element_from_string (struct it *);
1147 static bool next_element_from_c_string (struct it *);
1148 static bool next_element_from_buffer (struct it *);
1149 static bool next_element_from_composition (struct it *);
1150 static bool next_element_from_image (struct it *);
1151 static bool next_element_from_stretch (struct it *);
1152 static bool next_element_from_xwidget (struct it *);
1153 static void load_overlay_strings (struct it *, ptrdiff_t);
1154 static bool get_next_display_element (struct it *);
1155 static enum move_it_result
1156 move_it_in_display_line_to (struct it *, ptrdiff_t, int,
1157 enum move_operation_enum);
1158 static void get_visually_first_element (struct it *);
1159 static void compute_stop_pos (struct it *);
1160 static int face_before_or_after_it_pos (struct it *, bool);
1161 static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
1162 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
1163 static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
1164 Lisp_Object, struct text_pos *,
1165 ptrdiff_t, int, bool, bool);
1166 static int underlying_face_id (const struct it *);
1167
1168 #define face_before_it_pos(IT) face_before_or_after_it_pos (IT, true)
1169 #define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false)
1170
1171 #ifdef HAVE_WINDOW_SYSTEM
1172
1173 static void update_tool_bar (struct frame *, bool);
1174 static void gui_draw_bottom_divider (struct window *w);
1175 static void notice_overwritten_cursor (struct window *,
1176 enum glyph_row_area,
1177 int, int, int, int);
1178 static int normal_char_height (struct font *, int);
1179 static void normal_char_ascent_descent (struct font *, int, int *, int *);
1180
1181 static void append_stretch_glyph (struct it *, Lisp_Object,
1182 int, int, int);
1183
1184 static Lisp_Object get_it_property (struct it *, Lisp_Object);
1185 static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
1186 struct font *, int, bool);
1187 static int adjust_glyph_width_for_mouse_face (struct glyph *,
1188 struct glyph_row *,
1189 struct window *, struct face *,
1190 struct face *);
1191 static void get_cursor_offset_for_mouse_face (struct window *w,
1192 struct glyph_row *row,
1193 int *offset);
1194 #endif
1195
1196 static void produce_special_glyphs (struct it *, enum display_element_type);
1197 static void pad_mode_line (struct it *, bool);
1198 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
1199 static bool coords_in_mouse_face_p (struct window *, int, int);
1200 static void reset_box_start_end_flags (struct it *);
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214 int
1215 window_text_bottom_y (struct window *w)
1216 {
1217 int height = WINDOW_PIXEL_HEIGHT (w);
1218
1219 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1220
1221 if (window_wants_mode_line (w))
1222 height -= CURRENT_MODE_LINE_HEIGHT (w);
1223
1224 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1225
1226 return height;
1227 }
1228
1229
1230
1231
1232
1233 int
1234 window_box_width (struct window *w, enum glyph_row_area area)
1235 {
1236 int width = w->pixel_width;
1237
1238 if (!w->pseudo_window_p)
1239 {
1240 width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
1241 width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
1242
1243 if (area == TEXT_AREA)
1244 width -= (WINDOW_MARGINS_WIDTH (w)
1245 + WINDOW_FRINGES_WIDTH (w));
1246 else if (area == LEFT_MARGIN_AREA)
1247 width = WINDOW_LEFT_MARGIN_WIDTH (w);
1248 else if (area == RIGHT_MARGIN_AREA)
1249 width = WINDOW_RIGHT_MARGIN_WIDTH (w);
1250 }
1251
1252
1253
1254 return max (0, width);
1255 }
1256
1257
1258
1259
1260
1261 int
1262 window_box_height (struct window *w)
1263 {
1264 struct frame *f = XFRAME (w->frame);
1265 int height = WINDOW_PIXEL_HEIGHT (w);
1266
1267 eassert (height >= 0);
1268
1269 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1270 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1271
1272
1273
1274
1275
1276
1277
1278 if (window_wants_mode_line (w))
1279 {
1280 if (w->mode_line_height >= 0)
1281 height -= w->mode_line_height;
1282 else
1283 {
1284 struct glyph_row *ml_row
1285 = (w->current_matrix && w->current_matrix->rows
1286 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1287 : 0);
1288 if (ml_row && ml_row->mode_line_p)
1289 height -= ml_row->height;
1290 else
1291 height -= estimate_mode_line_height
1292 (f, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w));
1293 }
1294 }
1295
1296 if (window_wants_tab_line (w))
1297 {
1298 if (w->tab_line_height >= 0)
1299 height -= w->tab_line_height;
1300 else
1301 {
1302 struct glyph_row *tl_row
1303 = (w->current_matrix && w->current_matrix->rows
1304 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
1305 : 0);
1306 if (tl_row && tl_row->mode_line_p)
1307 height -= tl_row->height;
1308 else
1309 height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
1310 }
1311 }
1312
1313 if (window_wants_header_line (w))
1314 {
1315 if (w->header_line_height >= 0)
1316 height -= w->header_line_height;
1317 else
1318 {
1319 struct glyph_row *hl_row
1320 = (w->current_matrix && w->current_matrix->rows
1321 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1322 : 0);
1323 if (hl_row && hl_row->mode_line_p)
1324 height -= hl_row->height;
1325 else
1326 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1327 }
1328 }
1329
1330
1331
1332 return max (0, height);
1333 }
1334
1335
1336
1337
1338
1339 int
1340 window_box_left_offset (struct window *w, enum glyph_row_area area)
1341 {
1342 int x;
1343
1344 if (w->pseudo_window_p)
1345 return 0;
1346
1347 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1348
1349 if (area == TEXT_AREA)
1350 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1351 + window_box_width (w, LEFT_MARGIN_AREA));
1352 else if (area == RIGHT_MARGIN_AREA)
1353 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1354 + window_box_width (w, LEFT_MARGIN_AREA)
1355 + window_box_width (w, TEXT_AREA)
1356 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1357 ? 0
1358 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1359 else if (area == LEFT_MARGIN_AREA
1360 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1361 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1362
1363
1364 return min (x, w->pixel_width);
1365 }
1366
1367
1368
1369
1370
1371
1372 static int
1373 window_box_right_offset (struct window *w, enum glyph_row_area area)
1374 {
1375
1376 return min (window_box_left_offset (w, area) + window_box_width (w, area),
1377 w->pixel_width);
1378 }
1379
1380
1381
1382
1383
1384 int
1385 window_box_left (struct window *w, enum glyph_row_area area)
1386 {
1387 struct frame *f = XFRAME (w->frame);
1388 int x;
1389
1390 if (w->pseudo_window_p)
1391 return FRAME_INTERNAL_BORDER_WIDTH (f);
1392
1393 x = (WINDOW_LEFT_EDGE_X (w)
1394 + window_box_left_offset (w, area));
1395
1396 return x;
1397 }
1398
1399
1400
1401
1402
1403
1404 int
1405 window_box_right (struct window *w, enum glyph_row_area area)
1406 {
1407 return window_box_left (w, area) + window_box_width (w, area);
1408 }
1409
1410
1411
1412
1413
1414
1415
1416
1417 void
1418 window_box (struct window *w, enum glyph_row_area area, int *box_x,
1419 int *box_y, int *box_width, int *box_height)
1420 {
1421 if (box_width)
1422 *box_width = window_box_width (w, area);
1423 if (box_height)
1424 *box_height = window_box_height (w);
1425 if (box_x)
1426 *box_x = window_box_left (w, area);
1427 if (box_y)
1428 {
1429 *box_y = WINDOW_TOP_EDGE_Y (w);
1430 if (window_wants_tab_line (w))
1431 *box_y += CURRENT_TAB_LINE_HEIGHT (w);
1432 if (window_wants_header_line (w))
1433 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1434 }
1435 }
1436
1437 #ifdef HAVE_WINDOW_SYSTEM
1438
1439
1440
1441
1442
1443
1444
1445
1446 static void
1447 window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
1448 int *bottom_right_x, int *bottom_right_y)
1449 {
1450 window_box (w, ANY_AREA, top_left_x, top_left_y,
1451 bottom_right_x, bottom_right_y);
1452 *bottom_right_x += *top_left_x;
1453 *bottom_right_y += *top_left_y;
1454 }
1455
1456 #endif
1457
1458
1459
1460
1461
1462
1463
1464
1465 int
1466 line_bottom_y (struct it *it)
1467 {
1468 int line_height = it->max_ascent + it->max_descent;
1469 int line_top_y = it->current_y;
1470
1471 if (line_height == 0)
1472 {
1473 if (last_height)
1474 line_height = last_height;
1475 else if (IT_CHARPOS (*it) < ZV)
1476 {
1477 move_it_by_lines (it, 1);
1478 line_height = (it->max_ascent || it->max_descent
1479 ? it->max_ascent + it->max_descent
1480 : last_height);
1481 }
1482 else
1483 {
1484 struct glyph_row *row = it->glyph_row;
1485
1486
1487 it->glyph_row = NULL;
1488 it->what = IT_CHARACTER;
1489 it->c = ' ';
1490 it->len = 1;
1491 PRODUCE_GLYPHS (it);
1492 line_height = it->ascent + it->descent;
1493 it->glyph_row = row;
1494 }
1495 }
1496
1497 return line_top_y + line_height;
1498 }
1499
1500 DEFUN ("line-pixel-height", Fline_pixel_height,
1501 Sline_pixel_height, 0, 0, 0,
1502 doc:
1503
1504 )
1505 (void)
1506 {
1507 struct it it;
1508 struct text_pos pt;
1509 struct window *w = XWINDOW (selected_window);
1510 struct buffer *old_buffer = NULL;
1511 Lisp_Object result;
1512
1513 if (XBUFFER (w->contents) != current_buffer)
1514 {
1515 old_buffer = current_buffer;
1516 set_buffer_internal_1 (XBUFFER (w->contents));
1517 }
1518 SET_TEXT_POS (pt, PT, PT_BYTE);
1519 void *itdata = bidi_shelve_cache ();
1520 start_display (&it, w, pt);
1521
1522
1523
1524 move_it_by_lines (&it, 0);
1525 it.vpos = it.current_y = 0;
1526 last_height = 0;
1527 result = make_fixnum (line_bottom_y (&it));
1528 if (old_buffer)
1529 set_buffer_internal_1 (old_buffer);
1530
1531 bidi_unshelve_cache (itdata, false);
1532 return result;
1533 }
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549 int
1550 default_line_pixel_height (struct window *w)
1551 {
1552 struct frame *f = WINDOW_XFRAME (w);
1553 int height = FRAME_LINE_HEIGHT (f);
1554
1555 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1556 {
1557 struct buffer *b = XBUFFER (w->contents);
1558 Lisp_Object val = BVAR (b, extra_line_spacing);
1559
1560 if (NILP (val))
1561 val = BVAR (&buffer_defaults, extra_line_spacing);
1562 if (!NILP (val))
1563 {
1564 if (RANGED_FIXNUMP (0, val, INT_MAX))
1565 height += XFIXNAT (val);
1566 else if (FLOATP (val))
1567 {
1568 int addon = XFLOAT_DATA (val) * height + 0.5;
1569
1570 if (addon >= 0)
1571 height += addon;
1572 }
1573 }
1574 else
1575 height += f->extra_line_spacing;
1576 }
1577
1578 return height;
1579 }
1580
1581
1582
1583 static Lisp_Object
1584 string_from_display_spec (Lisp_Object spec)
1585 {
1586 if (VECTORP (spec))
1587 {
1588 for (ptrdiff_t i = 0; i < ASIZE (spec); i++)
1589 if (STRINGP (AREF (spec, i)))
1590 return AREF (spec, i);
1591 }
1592 else
1593 {
1594 for (; CONSP (spec); spec = XCDR (spec))
1595 if (STRINGP (XCAR (spec)))
1596 return XCAR (spec);
1597 }
1598 return spec;
1599 }
1600
1601
1602
1603
1604
1605 static int
1606 window_hscroll_limited (struct window *w, struct frame *f)
1607 {
1608 ptrdiff_t window_hscroll = w->hscroll;
1609 int window_text_width = window_box_width (w, TEXT_AREA);
1610 int colwidth = FRAME_COLUMN_WIDTH (f);
1611
1612 if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
1613 window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
1614
1615 return window_hscroll;
1616 }
1617
1618
1619
1620
1621
1622 static void
1623 reset_box_start_end_flags (struct it *it)
1624 {
1625
1626
1627 if (it->area == TEXT_AREA
1628
1629 && !(it->what == IT_IMAGE && it->image_id < 0))
1630 {
1631
1632
1633
1634
1635 if (it->face_box_p)
1636 it->start_of_box_run_p = false;
1637 it->end_of_box_run_p = false;
1638 }
1639 }
1640
1641
1642
1643
1644
1645
1646
1647 bool
1648 pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1649 int *rtop, int *rbot, int *rowh, int *vpos)
1650 {
1651 struct it it;
1652 void *itdata = bidi_shelve_cache ();
1653 struct text_pos top;
1654 bool visible_p = false;
1655 struct buffer *old_buffer = NULL;
1656 bool r2l = false;
1657
1658 if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
1659 return visible_p;
1660
1661 if (XBUFFER (w->contents) != current_buffer)
1662 {
1663 old_buffer = current_buffer;
1664 set_buffer_internal_1 (XBUFFER (w->contents));
1665 }
1666
1667 SET_TEXT_POS_FROM_MARKER (top, w->start);
1668
1669
1670
1671
1672 if (CHARPOS (top) > ZV || CHARPOS (top) < BEGV)
1673 SET_TEXT_POS (top, BEGV, BEGV_BYTE);
1674
1675
1676
1677 if (charpos >= 0 && CHARPOS (top) > charpos)
1678 return visible_p;
1679
1680
1681
1682
1683
1684
1685
1686
1687 int prev_mode_line_height = w->mode_line_height;
1688 int prev_header_line_height = w->header_line_height;
1689 int prev_tab_line_height = w->tab_line_height;
1690
1691 if (window_wants_mode_line (w))
1692 {
1693 Lisp_Object window_mode_line_format
1694 = window_parameter (w, Qmode_line_format);
1695
1696 w->mode_line_height
1697 = display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
1698 NILP (window_mode_line_format)
1699 ? BVAR (current_buffer, mode_line_format)
1700 : window_mode_line_format);
1701 }
1702
1703 if (window_wants_tab_line (w))
1704 {
1705 Lisp_Object window_tab_line_format
1706 = window_parameter (w, Qtab_line_format);
1707
1708 w->tab_line_height
1709 = display_mode_line (w, TAB_LINE_FACE_ID,
1710 NILP (window_tab_line_format)
1711 ? BVAR (current_buffer, tab_line_format)
1712 : window_tab_line_format);
1713 }
1714
1715 if (window_wants_header_line (w))
1716 {
1717 Lisp_Object window_header_line_format
1718 = window_parameter (w, Qheader_line_format);
1719
1720 w->header_line_height
1721 = display_mode_line (w, HEADER_LINE_FACE_ID,
1722 NILP (window_header_line_format)
1723 ? BVAR (current_buffer, header_line_format)
1724 : window_header_line_format);
1725 }
1726
1727 start_display (&it, w, top);
1728 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
1729 (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
1730
1731
1732
1733 if (!NILP (Vdisplay_line_numbers)
1734 && it.current_x >= it.first_visible_x
1735 && IT_CHARPOS (it) == charpos
1736 && !it.line_number_produced_p)
1737 {
1738
1739
1740
1741 if (!it.lnum_pixel_width)
1742 {
1743 struct it it2;
1744 void *it2data = NULL;
1745
1746 SAVE_IT (it2, it, it2data);
1747 move_it_by_lines (&it, 1);
1748 it2.lnum_pixel_width = it.lnum_pixel_width;
1749 RESTORE_IT (&it, &it2, it2data);
1750 }
1751 it.current_x += it.lnum_pixel_width;
1752 }
1753
1754 if (charpos >= 0
1755 && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
1756 && IT_CHARPOS (it) >= charpos)
1757
1758
1759
1760 || (it.bidi_p && it.bidi_it.scan_dir == -1
1761 && IT_CHARPOS (it) <= charpos)))
1762 {
1763
1764
1765
1766
1767
1768
1769 int top_x = it.current_x;
1770 int top_y = it.current_y;
1771 int window_top_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
1772 int bottom_y;
1773 struct it save_it;
1774 void *save_it_data = NULL;
1775
1776
1777 SAVE_IT (save_it, it, save_it_data);
1778 last_height = 0;
1779 bottom_y = line_bottom_y (&it);
1780 if (top_y < window_top_y)
1781 visible_p = bottom_y > window_top_y;
1782 else if (top_y < it.last_visible_y)
1783 visible_p = true;
1784 if (bottom_y >= it.last_visible_y
1785 && it.bidi_p && it.bidi_it.scan_dir == -1
1786 && IT_CHARPOS (it) < charpos)
1787 {
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798 int ten_more_lines = 10 * default_line_pixel_height (w);
1799
1800 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1801 MOVE_TO_POS | MOVE_TO_Y);
1802 if (it.current_y > top_y)
1803 visible_p = false;
1804
1805 }
1806 RESTORE_IT (&it, &save_it, save_it_data);
1807 if (visible_p)
1808 {
1809 if (it.method == GET_FROM_DISPLAY_VECTOR)
1810 {
1811
1812
1813 if (charpos < 2 || top.charpos >= charpos)
1814 top_x = it.glyph_row->x;
1815 else
1816 {
1817 struct it it2, it2_prev;
1818
1819
1820
1821
1822
1823
1824 start_display (&it2, w, top);
1825 it2.glyph_row = NULL;
1826 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
1827
1828
1829
1830
1831 if (IT_CHARPOS (it2) != charpos - 1)
1832 it2_prev = it2;
1833 else
1834 {
1835
1836
1837
1838 do {
1839 get_next_display_element (&it2);
1840 PRODUCE_GLYPHS (&it2);
1841 it2_prev = it2;
1842 set_iterator_to_next (&it2, true);
1843 } while (it2.method == GET_FROM_DISPLAY_VECTOR
1844 && IT_CHARPOS (it2) < charpos);
1845 }
1846 if (ITERATOR_AT_END_OF_LINE_P (&it2_prev)
1847 || it2_prev.current_x > it2_prev.last_visible_x)
1848 top_x = it.glyph_row->x;
1849 else
1850 {
1851 top_x = it2_prev.current_x;
1852 top_y = it2_prev.current_y;
1853 }
1854 }
1855 }
1856 else if (IT_CHARPOS (it) != charpos)
1857 {
1858 Lisp_Object cpos = make_fixnum (charpos);
1859 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1860 Lisp_Object string = string_from_display_spec (spec);
1861 struct text_pos tpos;
1862 bool newline_in_string
1863 = (STRINGP (string)
1864 && memchr (SDATA (string), '\n', SBYTES (string)));
1865
1866 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1867 bool replacing_spec_p
1868 = (!NILP (spec)
1869 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1870 charpos, FRAME_WINDOW_P (it.f)));
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887 if (replacing_spec_p)
1888 {
1889 Lisp_Object startpos, endpos;
1890 EMACS_INT start, end;
1891 struct it it3;
1892
1893
1894
1895 endpos =
1896 Fnext_single_char_property_change (cpos, Qdisplay,
1897 Qnil, Qnil);
1898 startpos =
1899 Fprevious_single_char_property_change (endpos, Qdisplay,
1900 Qnil, Qnil);
1901 start = XFIXNAT (startpos);
1902 end = XFIXNAT (endpos);
1903
1904
1905 start_display (&it3, w, top);
1906 if (start > CHARPOS (top))
1907 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
1908
1909
1910
1911
1912 if (it3.method == GET_FROM_BUFFER
1913 && (it3.c == '\n'
1914 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1915 move_it_by_lines (&it3, 1);
1916 else if (move_it_in_display_line_to (&it3, -1,
1917 it3.current_x
1918 + it3.pixel_width,
1919 MOVE_TO_X)
1920 == MOVE_LINE_CONTINUED)
1921 {
1922 move_it_by_lines (&it3, 1);
1923
1924
1925
1926 if (it3.line_wrap == WORD_WRAP)
1927 move_it_by_lines (&it3, -1);
1928 }
1929
1930
1931
1932 top_y = it3.current_y;
1933 if (it3.bidi_p)
1934 {
1935
1936
1937
1938
1939
1940 start_display (&it3, w, top);
1941 move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
1942 if (it3.current_y < top_y)
1943 top_y = it3.current_y;
1944 }
1945
1946
1947
1948 start_display (&it3, w, top);
1949 it3.glyph_row = NULL;
1950 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
1951
1952
1953
1954
1955
1956
1957
1958 bool it3_moved = false;
1959 int top_x_before_string = it3.current_x;
1960
1961
1962
1963
1964
1965 while (get_next_display_element (&it3))
1966 {
1967 if (!EQ (it3.object, string))
1968 top_x_before_string = it3.current_x;
1969 PRODUCE_GLYPHS (&it3);
1970 if ((it3.bidi_it.scan_dir == 1
1971 && IT_CHARPOS (it3) >= charpos)
1972 || (it3.bidi_it.scan_dir == -1
1973 && IT_CHARPOS (it3) <= charpos)
1974 || ITERATOR_AT_END_OF_LINE_P (&it3))
1975 break;
1976 it3_moved = true;
1977 set_iterator_to_next (&it3, false);
1978 }
1979 top_x = it3.current_x - it3.pixel_width;
1980
1981
1982
1983 if (!it3.line_number_produced_p)
1984 {
1985 if (it3.lnum_pixel_width > 0)
1986 {
1987 top_x += it3.lnum_pixel_width;
1988 top_x_before_string += it3.lnum_pixel_width;
1989 }
1990 else if (it.line_number_produced_p)
1991 {
1992 top_x += it.lnum_pixel_width;
1993 top_x_before_string += it3.lnum_pixel_width;
1994 }
1995 }
1996
1997
1998
1999
2000
2001
2002 if (it3_moved
2003 && newline_in_string
2004 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
2005 top_x = top_x_before_string;
2006 }
2007 }
2008
2009 *x = top_x;
2010
2011
2012
2013
2014 if (it.ascent == 0 && it.what == IT_IMAGE
2015 && it.method != GET_FROM_IMAGE
2016 && it.image_id < 0
2017 && it.max_ascent > 0)
2018 *y = max (top_y, window_top_y);
2019 else
2020 *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
2021 *rtop = max (0, window_top_y - top_y);
2022 *rbot = max (0, bottom_y - it.last_visible_y);
2023 *rowh = max (0, (min (bottom_y, it.last_visible_y)
2024 - max (top_y, window_top_y)));
2025 *vpos = it.vpos;
2026 if (it.bidi_it.paragraph_dir == R2L)
2027 r2l = true;
2028 }
2029 }
2030 else
2031 {
2032
2033
2034
2035 struct it it2;
2036 void *it2data = NULL;
2037
2038 SAVE_IT (it2, it, it2data);
2039 if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
2040 move_it_by_lines (&it, 1);
2041 if (charpos < IT_CHARPOS (it)
2042 || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
2043 {
2044 visible_p = true;
2045 RESTORE_IT (&it2, &it2, it2data);
2046 move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
2047 *x = it2.current_x;
2048 if (it2.ascent == 0 && it2.what == IT_IMAGE
2049 && it2.method != GET_FROM_IMAGE
2050 && it2.image_id < 0
2051 && it2.max_ascent > 0)
2052 *y = it2.current_y;
2053 else
2054 *y = it2.current_y + it2.max_ascent - it2.ascent;
2055 *rtop = max (0, -it2.current_y);
2056 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
2057 - it.last_visible_y));
2058 *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
2059 it.last_visible_y)
2060 - max (max (it2.current_y,
2061 WINDOW_TAB_LINE_HEIGHT (w)),
2062 WINDOW_HEADER_LINE_HEIGHT (w))));
2063 *vpos = it2.vpos;
2064 if (it2.bidi_it.paragraph_dir == R2L)
2065 r2l = true;
2066 }
2067 else
2068 bidi_unshelve_cache (it2data, true);
2069 }
2070 bidi_unshelve_cache (itdata, false);
2071
2072 if (old_buffer)
2073 set_buffer_internal_1 (old_buffer);
2074
2075 if (visible_p)
2076 {
2077 if (w->hscroll > 0)
2078 *x -=
2079 window_hscroll_limited (w, WINDOW_XFRAME (w))
2080 * WINDOW_FRAME_COLUMN_WIDTH (w);
2081
2082
2083
2084
2085
2086 if (r2l)
2087 *x = window_box_width (w, TEXT_AREA) - *x - 1;
2088 }
2089
2090 #if false
2091
2092 if (visible_p)
2093 fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
2094 charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
2095 else
2096 fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
2097 #endif
2098
2099
2100 w->mode_line_height = prev_mode_line_height;
2101 w->header_line_height = prev_header_line_height;
2102 w->tab_line_height = prev_tab_line_height;
2103
2104 return visible_p;
2105 }
2106
2107
2108
2109
2110
2111
2112
2113 static int
2114 check_char_and_length (const unsigned char *str, int *len)
2115 {
2116 int c = string_char_and_length (str, len);
2117 if (!CHAR_VALID_P (c))
2118
2119
2120
2121 c = '?';
2122
2123 return c;
2124 }
2125
2126
2127
2128
2129
2130
2131 static struct text_pos
2132 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
2133 {
2134 eassert (STRINGP (string) && nchars >= 0);
2135
2136 if (STRING_MULTIBYTE (string))
2137 {
2138 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
2139
2140 while (nchars--)
2141 {
2142 int len = BYTES_BY_CHAR_HEAD (*p);
2143 p += len;
2144 CHARPOS (pos) += 1;
2145 BYTEPOS (pos) += len;
2146 }
2147 }
2148 else
2149 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
2150
2151 return pos;
2152 }
2153
2154
2155
2156
2157
2158 static struct text_pos
2159 string_pos (ptrdiff_t charpos, Lisp_Object string)
2160 {
2161 struct text_pos pos;
2162 eassert (STRINGP (string));
2163 eassert (charpos >= 0);
2164 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
2165 return pos;
2166 }
2167
2168
2169
2170
2171
2172
2173 static struct text_pos
2174 c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
2175 {
2176 struct text_pos pos;
2177
2178 eassert (s != NULL);
2179 eassert (charpos >= 0);
2180
2181 if (multibyte_p)
2182 {
2183 SET_TEXT_POS (pos, 0, 0);
2184 while (charpos--)
2185 {
2186 int len = BYTES_BY_CHAR_HEAD (*s);
2187 s += len;
2188 CHARPOS (pos) += 1;
2189 BYTEPOS (pos) += len;
2190 }
2191 }
2192 else
2193 SET_TEXT_POS (pos, charpos, charpos);
2194
2195 return pos;
2196 }
2197
2198
2199
2200
2201
2202 static ptrdiff_t
2203 number_of_chars (const char *s, bool multibyte_p)
2204 {
2205 ptrdiff_t nchars;
2206
2207 if (multibyte_p)
2208 {
2209 ptrdiff_t rest = strlen (s);
2210 const unsigned char *p = (const unsigned char *) s;
2211
2212 for (nchars = 0; rest > 0; ++nchars)
2213 {
2214 int len = BYTES_BY_CHAR_HEAD (*p);
2215 rest -= len, p += len;
2216 }
2217 }
2218 else
2219 nchars = strlen (s);
2220
2221 return nchars;
2222 }
2223
2224
2225
2226
2227
2228
2229 static void
2230 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
2231 {
2232 eassert (STRINGP (string));
2233 eassert (CHARPOS (*newpos) >= CHARPOS (pos));
2234
2235 if (STRING_MULTIBYTE (string))
2236 *newpos = string_pos_nchars_ahead (pos, string,
2237 CHARPOS (*newpos) - CHARPOS (pos));
2238 else
2239 BYTEPOS (*newpos) = CHARPOS (*newpos);
2240 }
2241
2242
2243
2244
2245
2246 int
2247 estimate_mode_line_height (struct frame *f, enum face_id face_id)
2248 {
2249 #ifdef HAVE_WINDOW_SYSTEM
2250 if (FRAME_WINDOW_P (f))
2251 {
2252 int height = FONT_HEIGHT (FRAME_FONT (f));
2253
2254
2255
2256 if (FRAME_FACE_CACHE (f))
2257 {
2258 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2259 if (face)
2260 {
2261 if (face->font)
2262 height = normal_char_height (face->font, -1);
2263 if (face->box_horizontal_line_width > 0)
2264 height += 2 * face->box_horizontal_line_width;
2265 }
2266 }
2267
2268 return height;
2269 }
2270 #endif
2271
2272 return 1;
2273 }
2274
2275
2276
2277
2278
2279
2280 void
2281 pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2282 NativeRectangle *bounds, bool noclip)
2283 {
2284
2285 #ifdef HAVE_WINDOW_SYSTEM
2286 if (FRAME_WINDOW_P (f))
2287 {
2288
2289
2290 if (pix_x < 0)
2291 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
2292 if (pix_y < 0)
2293 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
2294
2295 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
2296 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
2297
2298 if (bounds)
2299 STORE_NATIVE_RECT (*bounds,
2300 FRAME_COL_TO_PIXEL_X (f, pix_x),
2301 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
2302 FRAME_COLUMN_WIDTH (f) - 1,
2303 FRAME_LINE_HEIGHT (f) - 1);
2304
2305
2306 if (!noclip)
2307 {
2308 if (pix_x < 0)
2309 pix_x = 0;
2310 else if (pix_x > FRAME_TOTAL_COLS (f))
2311 pix_x = FRAME_TOTAL_COLS (f);
2312
2313 if (pix_y < 0)
2314 pix_y = 0;
2315 else if (pix_y > FRAME_TOTAL_LINES (f))
2316 pix_y = FRAME_TOTAL_LINES (f);
2317 }
2318 }
2319 #endif
2320
2321 *x = pix_x;
2322 *y = pix_y;
2323 }
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334 struct glyph *
2335 x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2336 int *dx, int *dy, int *area)
2337 {
2338 struct glyph *glyph, *end;
2339 struct glyph_row *row = NULL;
2340 int x0, i;
2341
2342
2343 for (i = 0; i < w->current_matrix->nrows; ++i)
2344 {
2345 row = MATRIX_ROW (w->current_matrix, i);
2346 if (!row->enabled_p)
2347 return NULL;
2348 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
2349 break;
2350 }
2351
2352 *vpos = i;
2353 *hpos = 0;
2354
2355
2356 if (i == w->current_matrix->nrows)
2357 return NULL;
2358
2359
2360 if (w->pseudo_window_p)
2361 {
2362 *area = TEXT_AREA;
2363 x0 = 0;
2364 }
2365 else
2366 {
2367 if (x < window_box_left_offset (w, TEXT_AREA))
2368 {
2369 *area = LEFT_MARGIN_AREA;
2370 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
2371 }
2372 else if (x < window_box_right_offset (w, TEXT_AREA))
2373 {
2374 *area = TEXT_AREA;
2375 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
2376 }
2377 else
2378 {
2379 *area = RIGHT_MARGIN_AREA;
2380 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
2381 }
2382 }
2383
2384
2385 glyph = row->glyphs[*area];
2386 end = glyph + row->used[*area];
2387 x -= x0;
2388 while (glyph < end && x >= glyph->pixel_width)
2389 {
2390 x -= glyph->pixel_width;
2391 ++glyph;
2392 }
2393
2394 if (glyph == end)
2395 return NULL;
2396
2397 if (dx)
2398 {
2399 *dx = x;
2400 *dy = y - (row->y + row->ascent - glyph->ascent);
2401 }
2402
2403 *hpos = glyph - row->glyphs[*area];
2404 return glyph;
2405 }
2406
2407
2408
2409
2410 static void
2411 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
2412 {
2413 if (w->pseudo_window_p)
2414 {
2415
2416
2417 struct frame *f = XFRAME (w->frame);
2418 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
2419 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2420 }
2421 else
2422 {
2423 *x -= WINDOW_LEFT_EDGE_X (w);
2424 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2425 }
2426 }
2427
2428 #ifdef HAVE_WINDOW_SYSTEM
2429
2430
2431
2432
2433
2434 int
2435 get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int n)
2436 {
2437 Emacs_Rectangle r;
2438
2439 if (n <= 0)
2440 return 0;
2441
2442 if (s->row->full_width_p)
2443 {
2444
2445 r.x = WINDOW_LEFT_EDGE_X (s->w);
2446 if (s->row->mode_line_p)
2447 r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
2448 else
2449 r.width = WINDOW_PIXEL_WIDTH (s->w);
2450
2451
2452
2453 if (s->w->pseudo_window_p)
2454 r.height = s->row->visible_height;
2455 else
2456 r.height = s->height;
2457 }
2458 else
2459 {
2460
2461 r.x = window_box_left (s->w, s->area);
2462 r.width = window_box_width (s->w, s->area);
2463 r.height = s->row->visible_height;
2464 }
2465
2466 if (s->clip_head)
2467 if (r.x < s->clip_head->x)
2468 {
2469 if (r.width >= s->clip_head->x - r.x)
2470 r.width -= s->clip_head->x - r.x;
2471 else
2472 r.width = 0;
2473 r.x = s->clip_head->x;
2474 }
2475 if (s->clip_tail)
2476 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
2477 {
2478 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2479 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
2480 else
2481 r.width = 0;
2482 }
2483
2484
2485
2486
2487 if (s->for_overlaps)
2488 {
2489 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2490 r.height = window_text_bottom_y (s->w) - r.y;
2491
2492
2493
2494
2495
2496
2497 if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
2498 {
2499 Emacs_Rectangle rc, r_save = r;
2500
2501 rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
2502 rc.y = s->w->phys_cursor.y;
2503 rc.width = s->w->phys_cursor_width;
2504 rc.height = s->w->phys_cursor_height;
2505
2506 gui_intersect_rectangles (&r_save, &rc, &r);
2507 }
2508 }
2509 else
2510 {
2511
2512
2513
2514 if (!s->row->full_width_p
2515 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2516 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2517 else
2518 r.y = max (0, s->row->y);
2519 }
2520
2521 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
2522
2523
2524
2525 if (s->hl == DRAW_CURSOR)
2526 {
2527 struct glyph *glyph = s->first_glyph;
2528 int height, max_y;
2529
2530 if (s->x > r.x)
2531 {
2532 if (r.width >= s->x - r.x)
2533 r.width -= s->x - r.x;
2534 else
2535 r.width = 0;
2536 r.x = s->x;
2537 }
2538 r.width = min (r.width, glyph->pixel_width);
2539
2540
2541 height = min (glyph->ascent + glyph->descent,
2542 min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
2543 max_y = window_text_bottom_y (s->w) - height;
2544 max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
2545 if (s->ybase - glyph->ascent > max_y)
2546 {
2547 r.y = max_y;
2548 r.height = height;
2549 }
2550 else
2551 {
2552
2553 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2554 if (height < r.height)
2555 {
2556 max_y = r.y + r.height;
2557 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2558 r.height = min (max_y - r.y, height);
2559 }
2560 }
2561 }
2562
2563 if (s->row->clip)
2564 {
2565 Emacs_Rectangle r_save = r;
2566
2567 if (! gui_intersect_rectangles (&r_save, s->row->clip, &r))
2568 r.width = 0;
2569 }
2570
2571 if ((s->for_overlaps & OVERLAPS_BOTH) == 0
2572 || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
2573 {
2574 #ifdef CONVERT_FROM_EMACS_RECT
2575 CONVERT_FROM_EMACS_RECT (r, *rects);
2576 #else
2577 *rects = r;
2578 #endif
2579 return 1;
2580 }
2581 else
2582 {
2583
2584
2585
2586
2587 #ifdef CONVERT_FROM_EMACS_RECT
2588 Emacs_Rectangle rs[2];
2589 #else
2590 Emacs_Rectangle *rs = rects;
2591 #endif
2592 int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
2593
2594 if (s->for_overlaps & OVERLAPS_PRED)
2595 {
2596 rs[i] = r;
2597 if (r.y + r.height > row_y)
2598 {
2599 if (r.y < row_y)
2600 rs[i].height = row_y - r.y;
2601 else
2602 rs[i].height = 0;
2603 }
2604 i++;
2605 }
2606 if (s->for_overlaps & OVERLAPS_SUCC)
2607 {
2608 rs[i] = r;
2609 if (r.y < row_y + s->row->visible_height)
2610 {
2611 if (r.y + r.height > row_y + s->row->visible_height)
2612 {
2613 rs[i].y = row_y + s->row->visible_height;
2614 rs[i].height = r.y + r.height - rs[i].y;
2615 }
2616 else
2617 rs[i].height = 0;
2618 }
2619 i++;
2620 }
2621
2622 n = i;
2623 #ifdef CONVERT_FROM_EMACS_RECT
2624 for (i = 0; i < n; i++)
2625 CONVERT_FROM_EMACS_RECT (rs[i], rects[i]);
2626 #endif
2627 return n;
2628 }
2629 }
2630
2631
2632
2633
2634 void
2635 get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2636 {
2637 get_glyph_string_clip_rects (s, nr, 1);
2638 }
2639
2640
2641
2642
2643
2644
2645
2646 void
2647 get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2648 struct glyph *glyph, int *xp, int *yp, int *heightp)
2649 {
2650 struct frame *f = XFRAME (WINDOW_FRAME (w));
2651 int x, y, wd, h, h0, y0, ascent;
2652
2653
2654
2655
2656
2657 wd = glyph->pixel_width;
2658
2659 x = w->phys_cursor.x;
2660 if (x < 0)
2661 {
2662 wd += x;
2663 x = 0;
2664 }
2665
2666 if (glyph->type == STRETCH_GLYPH
2667 && !x_stretch_cursor_p)
2668 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2669 w->phys_cursor_width = wd;
2670
2671
2672
2673 y = w->phys_cursor.y;
2674 ascent = row->ascent;
2675
2676
2677
2678 if (!row->ends_at_zv_p && row->ascent < glyph->ascent)
2679 {
2680 y -= glyph->ascent - row->ascent;
2681 ascent = glyph->ascent;
2682 }
2683
2684
2685 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2686
2687 h = max (h0, ascent + glyph->descent);
2688
2689
2690 h = min (h, row->height);
2691 h0 = min (h0, ascent + glyph->descent);
2692
2693 y0 = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
2694 if (y < y0)
2695 {
2696 h = max (h - (y0 - y) + 1, h0);
2697 y = y0 - 1;
2698 }
2699 else
2700 {
2701 y0 = window_text_bottom_y (w) - h0;
2702 if (y > y0)
2703 {
2704 h += y - y0;
2705 y = y0;
2706 }
2707 }
2708
2709 *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
2710 *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2711 *heightp = h;
2712 }
2713
2714
2715
2716
2717
2718 void
2719 remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2720 {
2721 Lisp_Object window;
2722 struct window *w;
2723 struct glyph_row *r, *gr, *end_row;
2724 enum window_part part;
2725 enum glyph_row_area area;
2726 int x, y, width, height;
2727
2728 if (mouse_fine_grained_tracking)
2729 {
2730 STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
2731 return;
2732 }
2733
2734
2735
2736
2737 if (window_resize_pixelwise)
2738 {
2739 width = height = 1;
2740 goto virtual_glyph;
2741 }
2742 else if (!f->glyphs_initialized_p
2743 || (window = window_from_coordinates (f, gx, gy, &part, false, false),
2744 NILP (window)))
2745 {
2746 width = FRAME_SMALLEST_CHAR_WIDTH (f);
2747 height = FRAME_SMALLEST_FONT_HEIGHT (f);
2748 goto virtual_glyph;
2749 }
2750
2751 w = XWINDOW (window);
2752 width = WINDOW_FRAME_COLUMN_WIDTH (w);
2753 height = WINDOW_FRAME_LINE_HEIGHT (w);
2754
2755 x = window_relative_x_coord (w, part, gx);
2756 y = gy - WINDOW_TOP_EDGE_Y (w);
2757
2758 r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
2759 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
2760
2761 if (w->pseudo_window_p)
2762 {
2763 area = TEXT_AREA;
2764 part = ON_MODE_LINE;
2765 goto text_glyph;
2766 }
2767
2768 switch (part)
2769 {
2770 case ON_LEFT_MARGIN:
2771 area = LEFT_MARGIN_AREA;
2772 goto text_glyph;
2773
2774 case ON_RIGHT_MARGIN:
2775 area = RIGHT_MARGIN_AREA;
2776 goto text_glyph;
2777
2778 case ON_TAB_LINE:
2779 case ON_HEADER_LINE:
2780 case ON_MODE_LINE:
2781 gr = (part == ON_TAB_LINE
2782 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
2783 : (part == ON_HEADER_LINE
2784 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
2785 : MATRIX_MODE_LINE_ROW (w->current_matrix)));
2786 gy = gr->y;
2787 area = TEXT_AREA;
2788 goto text_glyph_row_found;
2789
2790 case ON_TEXT:
2791 area = TEXT_AREA;
2792
2793 text_glyph:
2794 gr = 0; gy = 0;
2795 for (; r <= end_row && r->enabled_p; ++r)
2796 if (r->y + r->height > y)
2797 {
2798 gr = r; gy = r->y;
2799 break;
2800 }
2801
2802 text_glyph_row_found:
2803 if (gr && gy <= y)
2804 {
2805 struct glyph *g = gr->glyphs[area];
2806 struct glyph *end = g + gr->used[area];
2807
2808 height = gr->height;
2809 for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
2810 if (gx + g->pixel_width > x)
2811 break;
2812
2813 if (g < end)
2814 {
2815 if (g->type == IMAGE_GLYPH)
2816 {
2817
2818
2819 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
2820 return;
2821 }
2822 width = g->pixel_width;
2823 }
2824 else
2825 {
2826
2827 x -= gx;
2828 gx += (x / width) * width;
2829 }
2830
2831 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2832 && part != ON_TAB_LINE)
2833 {
2834 gx += window_box_left_offset (w, area);
2835
2836
2837 height = min (height,
2838 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2839 }
2840 }
2841 else
2842 {
2843
2844 gx = (x / width) * width;
2845 y -= gy;
2846 gy += (y / height) * height;
2847 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2848 && part != ON_TAB_LINE)
2849
2850 height = min (height,
2851 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2852 }
2853 break;
2854
2855 case ON_LEFT_FRINGE:
2856 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2857 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2858 : window_box_right_offset (w, LEFT_MARGIN_AREA));
2859 width = WINDOW_LEFT_FRINGE_WIDTH (w);
2860 goto row_glyph;
2861
2862 case ON_RIGHT_FRINGE:
2863 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2864 ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
2865 : window_box_right_offset (w, TEXT_AREA));
2866 if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
2867 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
2868 && !WINDOW_RIGHTMOST_P (w))
2869 if (gx < WINDOW_PIXEL_WIDTH (w) - width)
2870
2871
2872 width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
2873 else
2874 width = WINDOW_PIXEL_WIDTH (w) - gx;
2875 else
2876 width = WINDOW_RIGHT_FRINGE_WIDTH (w);
2877
2878 goto row_glyph;
2879
2880 case ON_VERTICAL_BORDER:
2881 gx = WINDOW_PIXEL_WIDTH (w) - width;
2882 goto row_glyph;
2883
2884 case ON_VERTICAL_SCROLL_BAR:
2885 gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
2886 ? 0
2887 : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
2888 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2889 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
2890 : 0)));
2891 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2892
2893 row_glyph:
2894 gr = 0, gy = 0;
2895 for (; r <= end_row && r->enabled_p; ++r)
2896 if (r->y + r->height > y)
2897 {
2898 gr = r; gy = r->y;
2899 break;
2900 }
2901
2902 if (gr && gy <= y)
2903 height = gr->height;
2904 else
2905 {
2906
2907 y -= gy;
2908 gy += (y / height) * height;
2909 }
2910 break;
2911
2912 case ON_RIGHT_DIVIDER:
2913 gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
2914 width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
2915 gy = 0;
2916
2917 height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2918 goto add_edge;
2919
2920 case ON_BOTTOM_DIVIDER:
2921 gx = 0;
2922 width = WINDOW_PIXEL_WIDTH (w);
2923 gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2924 height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2925 goto add_edge;
2926
2927 default:
2928 ;
2929 virtual_glyph:
2930
2931
2932
2933
2934
2935
2936 if (gx < 0)
2937 gx -= width - 1;
2938 if (gy < 0)
2939 gy -= height - 1;
2940
2941 gx = (gx / width) * width;
2942 gy = (gy / height) * height;
2943
2944 goto store_rect;
2945 }
2946
2947 add_edge:
2948 gx += WINDOW_LEFT_EDGE_X (w);
2949 gy += WINDOW_TOP_EDGE_Y (w);
2950
2951 store_rect:
2952 STORE_NATIVE_RECT (*rect, gx, gy, width, height);
2953
2954
2955 #if false && defined HAVE_X_WINDOWS
2956 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2957 f->output_data.x->normal_gc,
2958 gx, gy, width, height);
2959 #endif
2960 }
2961
2962
2963 #endif
2964
2965 static void
2966 adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
2967 {
2968 eassert (w);
2969 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
2970 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
2971 w->window_end_vpos
2972 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
2973 }
2974
2975 static bool
2976 hscrolling_current_line_p (struct window *w)
2977 {
2978 return (!w->suspend_auto_hscroll
2979 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
2980 Qcurrent_line));
2981 }
2982
2983
2984
2985
2986
2987
2988
2989 static Lisp_Object
2990 safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
2991 {
2992 add_to_log ("Error during redisplay: %S signaled %S",
2993 Flist (nargs, args), arg);
2994 return Qnil;
2995 }
2996
2997
2998
2999
3000
3001 static Lisp_Object
3002 safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
3003 {
3004 Lisp_Object val;
3005
3006 if (inhibit_eval_during_redisplay)
3007 val = Qnil;
3008 else
3009 {
3010 ptrdiff_t i;
3011 specpdl_ref count = SPECPDL_INDEX ();
3012 Lisp_Object *args;
3013 USE_SAFE_ALLOCA;
3014 SAFE_ALLOCA_LISP (args, nargs);
3015
3016 args[0] = func;
3017 for (i = 1; i < nargs; i++)
3018 args[i] = va_arg (ap, Lisp_Object);
3019
3020 specbind (Qinhibit_redisplay, Qt);
3021 if (inhibit_quit)
3022 specbind (Qinhibit_quit, Qt);
3023
3024
3025 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
3026 safe_eval_handler);
3027 val = SAFE_FREE_UNBIND_TO (count, val);
3028 }
3029
3030 return val;
3031 }
3032
3033 Lisp_Object
3034 safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
3035 {
3036 Lisp_Object retval;
3037 va_list ap;
3038
3039 va_start (ap, func);
3040 retval = safe__call (false, nargs, func, ap);
3041 va_end (ap);
3042 return retval;
3043 }
3044
3045
3046
3047
3048 Lisp_Object
3049 safe_call1 (Lisp_Object fn, Lisp_Object arg)
3050 {
3051 return safe_call (2, fn, arg);
3052 }
3053
3054 static Lisp_Object
3055 safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
3056 {
3057 Lisp_Object retval;
3058 va_list ap;
3059
3060 va_start (ap, fn);
3061 retval = safe__call (inhibit_quit, 2, fn, ap);
3062 va_end (ap);
3063 return retval;
3064 }
3065
3066 Lisp_Object
3067 safe_eval (Lisp_Object sexpr)
3068 {
3069 return safe__call1 (false, Qeval, sexpr);
3070 }
3071
3072 static Lisp_Object
3073 safe__eval (bool inhibit_quit, Lisp_Object sexpr)
3074 {
3075 return safe__call1 (inhibit_quit, Qeval, sexpr);
3076 }
3077
3078
3079
3080
3081 Lisp_Object
3082 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
3083 {
3084 return safe_call (3, fn, arg1, arg2);
3085 }
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096 static void
3097 CHECK_IT (struct it *it)
3098 {
3099 #if false
3100 if (it->method == GET_FROM_STRING)
3101 {
3102 eassert (STRINGP (it->string));
3103 eassert (IT_STRING_CHARPOS (*it) >= 0);
3104 }
3105 else
3106 {
3107 eassert (IT_STRING_CHARPOS (*it) < 0);
3108 if (it->method == GET_FROM_BUFFER)
3109 {
3110
3111 eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
3112 }
3113 }
3114
3115 if (it->dpvec)
3116 eassert (it->current.dpvec_index >= 0);
3117 else
3118 eassert (it->current.dpvec_index < 0);
3119 #endif
3120 }
3121
3122
3123
3124
3125
3126 static void
3127 CHECK_WINDOW_END (struct window *w)
3128 {
3129 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3130 if (!MINI_WINDOW_P (w) && w->window_end_valid)
3131 {
3132 struct glyph_row *row;
3133 eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
3134 !row->enabled_p
3135 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
3136 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
3137 }
3138 #endif
3139 }
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164 void
3165 init_iterator (struct it *it, struct window *w,
3166 ptrdiff_t charpos, ptrdiff_t bytepos,
3167 struct glyph_row *row, enum face_id base_face_id)
3168 {
3169 enum face_id remapped_base_face_id = base_face_id;
3170 int body_width = 0, body_height = 0;
3171
3172
3173 eassert (w != NULL && it != NULL);
3174 eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
3175 && charpos <= ZV));
3176
3177
3178
3179
3180
3181 if (!inhibit_free_realized_faces)
3182 {
3183 if (face_change)
3184 {
3185 face_change = false;
3186 XFRAME (w->frame)->face_change = 0;
3187 free_all_realized_faces (Qnil);
3188 }
3189 else if (XFRAME (w->frame)->face_change)
3190 {
3191 XFRAME (w->frame)->face_change = 0;
3192 free_all_realized_faces (w->frame);
3193 }
3194 }
3195
3196
3197 if (! NILP (Vface_remapping_alist))
3198 remapped_base_face_id
3199 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
3200
3201
3202
3203 if (row == NULL)
3204 {
3205 if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
3206 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
3207 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
3208 else if (base_face_id == TAB_LINE_FACE_ID)
3209 row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
3210 else if (base_face_id == HEADER_LINE_FACE_ID)
3211 {
3212
3213 w->desired_matrix->tab_line_p = window_wants_tab_line (w);
3214 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
3215 }
3216 }
3217
3218
3219
3220 memclear (it, sizeof *it);
3221 it->current.overlay_string_index = -1;
3222 it->current.dpvec_index = -1;
3223 it->base_face_id = remapped_base_face_id;
3224 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3225 it->paragraph_embedding = L2R;
3226 it->bidi_it.w = w;
3227
3228
3229 XSETWINDOW (it->window, w);
3230 it->w = w;
3231 it->f = XFRAME (w->frame);
3232
3233 it->cmp_it.id = -1;
3234 it->cmp_it.parent_it = it;
3235
3236 if (max_redisplay_ticks > 0)
3237 update_redisplay_ticks (0, w);
3238
3239
3240 if (base_face_id == DEFAULT_FACE_ID
3241 && FRAME_WINDOW_P (it->f))
3242 {
3243 if (FIXNATP (BVAR (current_buffer, extra_line_spacing)))
3244 it->extra_line_spacing = XFIXNAT (BVAR (current_buffer, extra_line_spacing));
3245 else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
3246 it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
3247 * FRAME_LINE_HEIGHT (it->f));
3248 else if (it->f->extra_line_spacing > 0)
3249 it->extra_line_spacing = it->f->extra_line_spacing;
3250 }
3251
3252
3253
3254
3255
3256 if (FRAME_FACE_CACHE (it->f) == NULL)
3257 init_frame_faces (it->f);
3258 if (FRAME_FACE_CACHE (it->f)->used == 0)
3259 recompute_basic_faces (it->f);
3260
3261 it->override_ascent = -1;
3262
3263
3264 it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
3265
3266
3267
3268
3269 it->selective = (FIXNUMP (BVAR (current_buffer, selective_display))
3270 ? (clip_to_bounds
3271 (-1, XFIXNUM (BVAR (current_buffer, selective_display)),
3272 PTRDIFF_MAX))
3273 : (!NILP (BVAR (current_buffer, selective_display))
3274 ? -1 : 0));
3275 it->selective_display_ellipsis_p
3276 = !NILP (BVAR (current_buffer, selective_display_ellipses));
3277
3278
3279 it->dp = window_display_table (w);
3280
3281
3282 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
3283
3284 it->tab_width = SANE_TAB_WIDTH (current_buffer);
3285
3286
3287 if (TRUNCATE != 0)
3288 it->line_wrap = TRUNCATE;
3289 if (base_face_id == DEFAULT_FACE_ID
3290 && !it->w->hscroll
3291 && (WINDOW_FULL_WIDTH_P (it->w)
3292 || NILP (Vtruncate_partial_width_windows)
3293 || (FIXNUMP (Vtruncate_partial_width_windows)
3294
3295 && (XFIXNUM (Vtruncate_partial_width_windows)
3296 <= WINDOW_TOTAL_COLS (it->w))))
3297 && NILP (BVAR (current_buffer, truncate_lines)))
3298 it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
3299 ? WINDOW_WRAP : WORD_WRAP;
3300
3301
3302
3303
3304
3305
3306
3307 #ifdef HAVE_WINDOW_SYSTEM
3308 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3309 #endif
3310 {
3311 if (it->line_wrap == TRUNCATE)
3312 {
3313
3314 eassert (it->glyph_row == NULL);
3315 produce_special_glyphs (it, IT_TRUNCATION);
3316 it->truncation_pixel_width = it->pixel_width;
3317 }
3318 else
3319 {
3320
3321 eassert (it->glyph_row == NULL);
3322 produce_special_glyphs (it, IT_CONTINUATION);
3323 it->continuation_pixel_width = it->pixel_width;
3324 }
3325 }
3326
3327
3328
3329 it->pixel_width = it->ascent = it->descent = 0;
3330 it->phys_ascent = it->phys_descent = 0;
3331
3332
3333
3334
3335 it->glyph_row = row;
3336 it->area = TEXT_AREA;
3337
3338
3339
3340
3341
3342 if (base_face_id != DEFAULT_FACE_ID)
3343 {
3344
3345 it->first_visible_x = 0;
3346 it->last_visible_x =
3347 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3348 }
3349 else
3350 {
3351
3352
3353
3354
3355
3356
3357 if (hscrolling_current_line_p (w))
3358 {
3359 if (w->min_hscroll > 0)
3360 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
3361 else
3362 it->first_visible_x = 0;
3363 }
3364 else
3365 it->first_visible_x =
3366 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
3367
3368 body_width = window_box_width (w, TEXT_AREA);
3369 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3370 && body_width != w->old_body_pixel_width)
3371 FRAME_WINDOW_CHANGE (it->f) = true;
3372 it->last_visible_x = it->first_visible_x + body_width;
3373
3374
3375
3376
3377 if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
3378 {
3379 if (it->line_wrap == TRUNCATE)
3380 it->last_visible_x -= it->truncation_pixel_width;
3381 else
3382 it->last_visible_x -= it->continuation_pixel_width;
3383 }
3384
3385 it->tab_line_p = window_wants_tab_line (w);
3386 it->header_line_p = window_wants_header_line (w);
3387 body_height = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
3388 it->current_y = body_height + w->vscroll;
3389 }
3390
3391
3392 if (!FRAME_WINDOW_P (it->f)
3393 && !WINDOW_RIGHTMOST_P (it->w))
3394 it->last_visible_x -= 1;
3395
3396 it->last_visible_y = window_text_bottom_y (w);
3397 body_height += it->last_visible_y;
3398 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3399 && body_height != w->old_body_pixel_height)
3400 FRAME_WINDOW_CHANGE (it->f) = true;
3401
3402
3403
3404 if (base_face_id != DEFAULT_FACE_ID)
3405 {
3406 struct face *face;
3407
3408 it->face_id = remapped_base_face_id;
3409
3410
3411
3412 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3413 if (face && face->box != FACE_NO_BOX)
3414 {
3415 int box_thickness = face->box_vertical_line_width;
3416 it->face_box_p = true;
3417 it->start_of_box_run_p = true;
3418
3419
3420 if (box_thickness > 0)
3421 it->last_visible_x -= box_thickness;
3422 }
3423 }
3424
3425
3426
3427 if (charpos >= BUF_BEG (current_buffer))
3428 {
3429 it->stop_charpos = charpos;
3430 it->end_charpos = ZV;
3431 eassert (charpos == BYTE_TO_CHAR (bytepos));
3432 IT_CHARPOS (*it) = charpos;
3433 IT_BYTEPOS (*it) = bytepos;
3434
3435
3436
3437 it->face_id = it->base_face_id;
3438
3439 it->start = it->current;
3440
3441
3442
3443
3444
3445
3446
3447 it->bidi_p =
3448 !redisplay__inhibit_bidi
3449 && !NILP (BVAR (current_buffer, bidi_display_reordering))
3450 && it->multibyte_p;
3451
3452
3453
3454 if (it->bidi_p)
3455 {
3456
3457
3458
3459
3460 if (base_face_id == DEFAULT_FACE_ID
3461 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
3462 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
3463 {
3464 if (it->line_wrap == TRUNCATE)
3465 it->last_visible_x -= it->truncation_pixel_width;
3466 else
3467 it->last_visible_x -= it->continuation_pixel_width;
3468 }
3469
3470
3471 if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3472 Qleft_to_right))
3473 it->paragraph_embedding = L2R;
3474 else if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3475 Qright_to_left))
3476 it->paragraph_embedding = R2L;
3477 else
3478 it->paragraph_embedding = NEUTRAL_DIR;
3479 bidi_unshelve_cache (NULL, false);
3480 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
3481 &it->bidi_it);
3482 }
3483
3484
3485
3486 it->medium_narrowing_begv = 0;
3487
3488
3489 reseat (it, it->current.pos, true);
3490 }
3491
3492 CHECK_IT (it);
3493 }
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581 static int
3582 get_narrowed_width (struct window *w)
3583 {
3584
3585
3586 int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
3587
3588
3589
3590 int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
3591 - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
3592 || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
3593 return fact * max (1, width);
3594 }
3595
3596 static int
3597 get_narrowed_len (struct window *w)
3598 {
3599 int height = window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS);
3600 return get_narrowed_width (w) * max (1, height);
3601 }
3602
3603 static ptrdiff_t
3604 get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
3605 {
3606 int len = get_narrowed_len (w);
3607 return max ((pos / len - 1) * len, BEGV);
3608 }
3609
3610 static ptrdiff_t
3611 get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
3612 {
3613 int len = get_narrowed_len (w);
3614 return min ((pos / len + 1) * len, ZV);
3615 }
3616
3617
3618
3619
3620
3621
3622 static ptrdiff_t
3623 get_nearby_bol_pos (ptrdiff_t pos)
3624 {
3625 ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = pos;
3626 int dist;
3627 for (dist = 500; dist <= 500000; dist *= 10)
3628 {
3629 pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
3630 start = pos - dist < BEGV ? BEGV : pos - dist;
3631 for (cur = start; cur < pos; cur = next)
3632 {
3633 next = find_newline1 (cur, CHAR_TO_BYTE (cur),
3634 pos, pos_bytepos,
3635 1, &found, NULL, false);
3636 if (found)
3637 bol = next;
3638 else
3639 break;
3640 }
3641 if (bol >= BEGV || start == BEGV)
3642 break;
3643 else
3644 pos = pos - dist < BEGV ? BEGV : pos - dist;
3645 }
3646 eassert (bol <= init_pos);
3647 return bol;
3648 }
3649
3650 ptrdiff_t
3651 get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
3652 {
3653 int len = get_narrowed_width (w);
3654 ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
3655 return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
3656 }
3657
3658 ptrdiff_t
3659 get_large_narrowing_begv (ptrdiff_t pos)
3660 {
3661 if (long_line_optimizations_region_size <= 0)
3662 return BEGV;
3663 int len = long_line_optimizations_region_size / 2;
3664 int begv = max (pos - len, BEGV);
3665 int limit = long_line_optimizations_bol_search_limit;
3666 while (limit > 0)
3667 {
3668 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3669 return begv;
3670 begv--;
3671 limit--;
3672 }
3673 return begv;
3674 }
3675
3676 ptrdiff_t
3677 get_large_narrowing_zv (ptrdiff_t pos)
3678 {
3679 if (long_line_optimizations_region_size <= 0)
3680 return ZV;
3681 int len = long_line_optimizations_region_size / 2;
3682 return min (pos + len, ZV);
3683 }
3684
3685 static void
3686 unwind_narrowed_begv (Lisp_Object point_min)
3687 {
3688 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3689 }
3690
3691
3692
3693
3694 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
3695 do { \
3696 if (IT->medium_narrowing_begv) \
3697 { \
3698 specpdl_ref count = SPECPDL_INDEX (); \
3699 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3700 SET_BUF_BEGV (current_buffer, BV); \
3701 DST = EXPR; \
3702 unbind_to (count, Qnil); \
3703 } \
3704 else \
3705 DST = EXPR; \
3706 } while (0)
3707
3708
3709
3710 void
3711 start_display (struct it *it, struct window *w, struct text_pos pos)
3712 {
3713 struct glyph_row *row;
3714 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
3715
3716 row = w->desired_matrix->rows + first_vpos;
3717 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3718 it->first_vpos = first_vpos;
3719
3720
3721
3722 if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
3723 {
3724 int first_y = it->current_y;
3725
3726
3727
3728 bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
3729 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
3730 if (!start_at_line_beg_p)
3731 {
3732 int new_x;
3733
3734 reseat_at_previous_visible_line_start (it);
3735 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
3736
3737 new_x = it->current_x + it->pixel_width;
3738
3739
3740
3741
3742
3743
3744
3745 if (it->current_x > 0
3746 && it->line_wrap != TRUNCATE
3747 && (
3748 new_x > it->last_visible_x
3749
3750
3751 || (new_x == it->last_visible_x
3752 && FRAME_WINDOW_P (it->f)
3753 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
3754 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
3755 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
3756 {
3757 if ((it->current.dpvec_index >= 0
3758 || it->current.overlay_string_index >= 0)
3759
3760
3761
3762
3763
3764 && it->c != '\n')
3765 {
3766 set_iterator_to_next (it, true);
3767 move_it_in_display_line_to (it, -1, -1, 0);
3768 }
3769
3770 it->continuation_lines_width += it->current_x;
3771 }
3772
3773
3774
3775
3776
3777 else if (it->current.dpvec_index >= 0)
3778 it->current.dpvec_index = 0;
3779
3780
3781
3782
3783 it->max_ascent = it->max_descent = 0;
3784 it->max_phys_ascent = it->max_phys_descent = 0;
3785
3786 it->current_y = first_y;
3787 it->vpos = 0;
3788 it->current_x = it->hpos = 0;
3789 }
3790 }
3791 }
3792
3793
3794
3795
3796
3797 static bool
3798 in_ellipses_for_invisible_text_p (struct display_pos *pos, struct window *w)
3799 {
3800 Lisp_Object prop, window;
3801 bool ellipses_p = false;
3802 ptrdiff_t charpos = CHARPOS (pos->pos);
3803
3804
3805
3806
3807
3808 if (pos->dpvec_index >= 0
3809 && pos->overlay_string_index < 0
3810 && CHARPOS (pos->string_pos) < 0
3811 && charpos > BEGV
3812 && (XSETWINDOW (window, w),
3813 prop = Fget_char_property (make_fixnum (charpos),
3814 Qinvisible, window),
3815 TEXT_PROP_MEANS_INVISIBLE (prop) == 0))
3816 {
3817 prop = Fget_char_property (make_fixnum (charpos - 1), Qinvisible,
3818 window);
3819 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
3820 }
3821
3822 return ellipses_p;
3823 }
3824
3825
3826
3827
3828
3829
3830
3831 static bool
3832 init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
3833 {
3834 ptrdiff_t charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3835 int i;
3836 bool overlay_strings_with_newlines = false;
3837
3838
3839
3840
3841
3842 if (in_ellipses_for_invisible_text_p (pos, w))
3843 {
3844 --charpos;
3845 bytepos = 0;
3846 }
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
3858
3859
3860
3861
3862 for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
3863 {
3864 const char *s = SSDATA (it->overlay_strings[i]);
3865 const char *e = s + SBYTES (it->overlay_strings[i]);
3866
3867 while (s < e && *s != '\n')
3868 ++s;
3869
3870 if (s < e)
3871 {
3872 overlay_strings_with_newlines = true;
3873 break;
3874 }
3875 }
3876
3877
3878
3879 if (pos->overlay_string_index >= 0)
3880 {
3881 int relative_index;
3882
3883
3884
3885
3886
3887 if (it->method == GET_FROM_IMAGE)
3888 pop_it (it);
3889
3890
3891
3892
3893 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
3894 {
3895 ptrdiff_t n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
3896 it->current.overlay_string_index = 0;
3897 while (n--)
3898 {
3899 load_overlay_strings (it, 0);
3900 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
3901 }
3902 }
3903
3904 it->current.overlay_string_index = pos->overlay_string_index;
3905 relative_index = (it->current.overlay_string_index
3906 % OVERLAY_STRING_CHUNK_SIZE);
3907 it->string = it->overlay_strings[relative_index];
3908 eassert (STRINGP (it->string));
3909 it->current.string_pos = pos->string_pos;
3910 it->method = GET_FROM_STRING;
3911 it->end_charpos = SCHARS (it->string);
3912
3913 if (it->bidi_p)
3914 {
3915 it->bidi_it.string.lstring = it->string;
3916 it->bidi_it.string.s = NULL;
3917 it->bidi_it.string.schars = SCHARS (it->string);
3918 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
3919 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
3920 it->bidi_it.string.unibyte = !it->multibyte_p;
3921 it->bidi_it.w = it->w;
3922 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3923 FRAME_WINDOW_P (it->f), &it->bidi_it);
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933 if (CHARPOS (pos->string_pos) == 0)
3934 {
3935 get_visually_first_element (it);
3936 if (IT_STRING_CHARPOS (*it) != 0)
3937 do {
3938
3939 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
3940 bidi_move_to_visually_next (&it->bidi_it);
3941 } while (it->bidi_it.charpos != 0);
3942 }
3943 eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
3944 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
3945 }
3946 }
3947
3948 if (CHARPOS (pos->string_pos) >= 0)
3949 {
3950
3951
3952
3953 it->current.string_pos = pos->string_pos;
3954 eassert (STRINGP (it->string));
3955 if (it->bidi_p)
3956 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3957 FRAME_WINDOW_P (it->f), &it->bidi_it);
3958 }
3959
3960
3961
3962 if (pos->dpvec_index >= 0)
3963 {
3964 if (it->dpvec == NULL)
3965 get_next_display_element (it);
3966 eassert (it->dpvec && it->current.dpvec_index == 0);
3967 it->current.dpvec_index = pos->dpvec_index;
3968 }
3969
3970 CHECK_IT (it);
3971 return !overlay_strings_with_newlines;
3972 }
3973
3974
3975
3976
3977
3978 static void
3979 init_to_row_start (struct it *it, struct window *w, struct glyph_row *row)
3980 {
3981 init_from_display_pos (it, w, &row->start);
3982 it->start = row->start;
3983 it->continuation_lines_width = row->continuation_lines_width;
3984 CHECK_IT (it);
3985 }
3986
3987
3988
3989
3990
3991
3992
3993
3994 static bool
3995 init_to_row_end (struct it *it, struct window *w, struct glyph_row *row)
3996 {
3997 bool success = false;
3998
3999 if (init_from_display_pos (it, w, &row->end))
4000 {
4001 if (row->continued_p)
4002 it->continuation_lines_width
4003 = row->continuation_lines_width + row->pixel_width;
4004 CHECK_IT (it);
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014 if (get_next_display_element (it)
4015 && (it->bidi_it.scan_dir == -1 && it->cmp_it.id >= 0))
4016 success = false;
4017 else
4018 success = true;
4019 }
4020
4021 return success;
4022 }
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035 static void
4036 handle_stop (struct it *it)
4037 {
4038 enum prop_handled handled;
4039 bool handle_overlay_change_p;
4040 struct props *p;
4041
4042 it->dpvec = NULL;
4043 it->current.dpvec_index = -1;
4044 handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
4045 it->ellipsis_p = false;
4046
4047
4048 if (it->selective_display_ellipsis_p)
4049 it->saved_face_id = it->face_id;
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093 do
4094 {
4095 handled = HANDLED_NORMALLY;
4096
4097
4098 for (p = it_props; p->handler; ++p)
4099 {
4100 handled = p->handler (it);
4101
4102 if (handled == HANDLED_RECOMPUTE_PROPS)
4103 break;
4104 else if (handled == HANDLED_RETURN)
4105 {
4106
4107
4108 if (!handle_overlay_change_p
4109 || it->sp > 1
4110
4111
4112
4113
4114
4115
4116 || (it->current.overlay_string_index < 0
4117 && !get_overlay_strings_1 (it, 0, false)))
4118 {
4119 if (it->ellipsis_p)
4120 setup_for_ellipsis (it, 0);
4121
4122
4123
4124
4125
4126 if (STRINGP (it->string) && !SCHARS (it->string))
4127 pop_it (it);
4128 return;
4129 }
4130 else if (STRINGP (it->string) && !SCHARS (it->string))
4131 pop_it (it);
4132 else
4133 {
4134 it->string_from_display_prop_p = false;
4135 it->from_disp_prop_p = false;
4136 handle_overlay_change_p = false;
4137 }
4138 handled = HANDLED_RECOMPUTE_PROPS;
4139 break;
4140 }
4141 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
4142 handle_overlay_change_p = false;
4143 }
4144
4145 if (handled != HANDLED_RECOMPUTE_PROPS)
4146 {
4147
4148
4149 if (it->method == GET_FROM_DISPLAY_VECTOR)
4150 handle_overlay_change_p = false;
4151
4152
4153
4154
4155 if (handle_overlay_change_p)
4156 handled = handle_overlay_change (it);
4157 }
4158
4159 if (it->ellipsis_p)
4160 {
4161 setup_for_ellipsis (it, 0);
4162 break;
4163 }
4164 }
4165 while (handled == HANDLED_RECOMPUTE_PROPS);
4166
4167
4168 if (handled == HANDLED_NORMALLY)
4169 compute_stop_pos (it);
4170 }
4171
4172
4173
4174
4175
4176 static void
4177 compute_stop_pos (struct it *it)
4178 {
4179 register INTERVAL iv, next_iv;
4180 Lisp_Object object, limit, position;
4181 ptrdiff_t charpos, bytepos, cmp_limit_pos = -1;
4182
4183 if (STRINGP (it->string))
4184 {
4185
4186
4187 it->stop_charpos = it->end_charpos;
4188 object = it->string;
4189 limit = Qnil;
4190 charpos = IT_STRING_CHARPOS (*it);
4191 bytepos = IT_STRING_BYTEPOS (*it);
4192 }
4193 else
4194 {
4195 ptrdiff_t pos;
4196
4197
4198
4199 if (it->end_charpos > ZV)
4200 it->end_charpos = ZV;
4201 it->stop_charpos = it->end_charpos;
4202
4203
4204
4205
4206
4207 charpos = IT_CHARPOS (*it);
4208 bytepos = IT_BYTEPOS (*it);
4209 pos = next_overlay_change (charpos);
4210 if (pos < it->stop_charpos)
4211 it->stop_charpos = pos;
4212
4213 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
4214 && !NILP (Vauto_composition_mode)
4215 && composition_break_at_point
4216 && charpos < PT && PT < it->stop_charpos)
4217 it->stop_charpos = PT;
4218
4219
4220
4221 XSETBUFFER (object, current_buffer);
4222 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4223
4224
4225
4226
4227
4228
4229 if (!composition_break_at_point
4230 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
4231 && !NILP (Vauto_composition_mode))
4232 {
4233 ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
4234 bool found = false;
4235
4236 if (pos > ZV)
4237 pos = ZV;
4238 if (endpos > ZV)
4239 endpos = ZV;
4240 ptrdiff_t bpos = CHAR_TO_BYTE (pos);
4241 while (pos < endpos)
4242 {
4243 int ch = fetch_char_advance_no_check (&pos, &bpos);
4244 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\f')
4245 {
4246 found = true;
4247 break;
4248 }
4249 }
4250 if (found)
4251 {
4252 pos--;
4253 cmp_limit_pos = pos;
4254 }
4255 else if (it->stop_charpos < endpos)
4256 pos = it->stop_charpos;
4257 else
4258 {
4259
4260 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4261 }
4262 }
4263 limit = make_fixnum (pos);
4264 }
4265
4266
4267
4268 position = make_fixnum (charpos);
4269 iv = validate_interval_range (object, &position, &position, false);
4270 if (iv)
4271 {
4272 Lisp_Object values_here[LAST_PROP_IDX];
4273 struct props *p;
4274
4275
4276 for (p = it_props; p->handler; ++p)
4277 values_here[p->idx] = textget (iv->plist,
4278 builtin_lisp_symbol (p->name));
4279
4280
4281
4282 for (next_iv = next_interval (iv);
4283 (next_iv
4284 && (NILP (limit)
4285 || XFIXNAT (limit) > next_iv->position));
4286 next_iv = next_interval (next_iv))
4287 {
4288 for (p = it_props; p->handler; ++p)
4289 {
4290 Lisp_Object new_value = textget (next_iv->plist,
4291 builtin_lisp_symbol (p->name));
4292 if (!EQ (values_here[p->idx], new_value))
4293 break;
4294 }
4295
4296 if (p->handler)
4297 break;
4298 }
4299
4300 if (next_iv)
4301 {
4302 if (FIXNUMP (limit)
4303 && next_iv->position >= XFIXNAT (limit))
4304
4305 it->stop_charpos = min (XFIXNAT (limit), it->stop_charpos);
4306 else
4307
4308 it->stop_charpos = min (it->stop_charpos, next_iv->position);
4309 }
4310 }
4311
4312 if (it->cmp_it.id < 0
4313 && (STRINGP (it->string)
4314 || ((!it->bidi_p || it->bidi_it.scan_dir >= 0)
4315 && it->cmp_it.stop_pos <= IT_CHARPOS (*it))))
4316 {
4317 ptrdiff_t stoppos = it->end_charpos;
4318
4319
4320
4321
4322 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4323 stoppos = -1;
4324 else if (cmp_limit_pos > 0)
4325 stoppos = cmp_limit_pos;
4326
4327
4328
4329 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
4330 stoppos, it->string, false);
4331 }
4332
4333 eassert (STRINGP (it->string)
4334 || (it->stop_charpos >= BEGV
4335 && it->stop_charpos >= IT_CHARPOS (*it)));
4336 }
4337
4338
4339
4340
4341 #define MAX_DISP_SCAN 250
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355 ptrdiff_t
4356 compute_display_string_pos (struct text_pos *position,
4357 struct bidi_string_data *string,
4358 struct window *w,
4359 bool frame_window_p, int *disp_prop)
4360 {
4361
4362 Lisp_Object object, object1;
4363 Lisp_Object pos, spec, limpos;
4364 bool string_p = string && (STRINGP (string->lstring) || string->s);
4365 ptrdiff_t eob = string_p ? string->schars : ZV;
4366 ptrdiff_t begb = string_p ? 0 : BEGV;
4367 ptrdiff_t bufpos, charpos = CHARPOS (*position);
4368 ptrdiff_t lim =
4369 (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
4370 struct text_pos tpos;
4371 int rv = 0;
4372
4373 if (string && STRINGP (string->lstring))
4374 object1 = object = string->lstring;
4375 else if (w && !string_p)
4376 {
4377 XSETWINDOW (object, w);
4378 object1 = Qnil;
4379 }
4380 else
4381 object1 = object = Qnil;
4382
4383 *disp_prop = 1;
4384
4385 if (charpos >= eob
4386
4387
4388 || string->from_disp_str
4389
4390 || (string->s && !STRINGP (object)))
4391 {
4392 *disp_prop = 0;
4393 return eob;
4394 }
4395
4396
4397
4398 pos = make_fixnum (charpos);
4399 if (STRINGP (object))
4400 bufpos = string->bufpos;
4401 else
4402 bufpos = charpos;
4403 tpos = *position;
4404 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
4405 && (charpos <= begb
4406 || !EQ (Fget_char_property (make_fixnum (charpos - 1), Qdisplay,
4407 object),
4408 spec))
4409 && (rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos, bufpos,
4410 frame_window_p)))
4411 {
4412 if (rv == 2)
4413 *disp_prop = 2;
4414 return charpos;
4415 }
4416
4417
4418
4419 limpos = make_fixnum (lim);
4420 do {
4421 pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos);
4422 CHARPOS (tpos) = XFIXNAT (pos);
4423 if (CHARPOS (tpos) >= lim)
4424 {
4425 *disp_prop = 0;
4426 break;
4427 }
4428 if (STRINGP (object))
4429 BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
4430 else
4431 BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
4432 spec = Fget_char_property (pos, Qdisplay, object);
4433 if (!STRINGP (object))
4434 bufpos = CHARPOS (tpos);
4435 } while (NILP (spec)
4436 || !(rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos,
4437 bufpos, frame_window_p)));
4438 if (rv == 2)
4439 *disp_prop = 2;
4440
4441 return CHARPOS (tpos);
4442 }
4443
4444
4445
4446
4447
4448
4449 ptrdiff_t
4450 compute_display_string_end (ptrdiff_t charpos, struct bidi_string_data *string)
4451 {
4452
4453 Lisp_Object object =
4454 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
4455 Lisp_Object pos = make_fixnum (charpos);
4456 ptrdiff_t eob =
4457 (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
4458
4459 if (charpos >= eob || (string->s && !STRINGP (object)))
4460 return eob;
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476 if (NILP (Fget_char_property (pos, Qdisplay, object)))
4477 return -1;
4478
4479
4480
4481 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
4482
4483 return XFIXNAT (pos);
4484 }
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496 static enum prop_handled
4497 handle_fontified_prop (struct it *it)
4498 {
4499 Lisp_Object prop, pos;
4500 enum prop_handled handled = HANDLED_NORMALLY;
4501
4502 if (!NILP (Vmemory_full))
4503 return handled;
4504
4505
4506
4507
4508
4509 if (!STRINGP (it->string)
4510 && it->s == NULL
4511 && !NILP (Vfontification_functions)
4512 && !(input_was_pending && redisplay_skip_fontification_on_input)
4513 && !NILP (Vrun_hooks)
4514 && (pos = make_fixnum (IT_CHARPOS (*it)),
4515 prop = Fget_char_property (pos, Qfontified, Qnil),
4516
4517
4518 NILP (prop) && IT_CHARPOS (*it) < Z))
4519 {
4520 specpdl_ref count = SPECPDL_INDEX ();
4521 Lisp_Object val;
4522 struct buffer *obuf = current_buffer;
4523 ptrdiff_t begv = BEGV, zv = ZV;
4524 bool old_clip_changed = current_buffer->clip_changed;
4525 bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
4526
4527 val = Vfontification_functions;
4528 specbind (Qfontification_functions, Qnil);
4529
4530 eassert (it->end_charpos == ZV);
4531
4532 if (current_buffer->long_line_optimizations_p
4533 && long_line_optimizations_region_size > 0)
4534 {
4535 ptrdiff_t begv = it->large_narrowing_begv;
4536 ptrdiff_t zv = it->large_narrowing_zv;
4537 ptrdiff_t charpos = IT_CHARPOS (*it);
4538 if (charpos < begv || charpos > zv)
4539 {
4540 begv = get_large_narrowing_begv (charpos);
4541 zv = get_large_narrowing_zv (charpos);
4542 }
4543 if (begv != BEG || zv != Z)
4544 labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
4545 Qlong_line_optimizations_in_fontification_functions);
4546 }
4547
4548
4549
4550 it->f->inhibit_clear_image_cache = true;
4551
4552 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
4553 safe_call1 (val, pos);
4554 else
4555 {
4556 Lisp_Object fns, fn;
4557
4558 fns = Qnil;
4559
4560 for (; CONSP (val); val = XCDR (val))
4561 {
4562 fn = XCAR (val);
4563
4564 if (EQ (fn, Qt))
4565 {
4566
4567
4568
4569
4570
4571 for (fns = Fdefault_value (Qfontification_functions);
4572 CONSP (fns);
4573 fns = XCDR (fns))
4574 {
4575 fn = XCAR (fns);
4576 if (!EQ (fn, Qt))
4577 safe_call1 (fn, pos);
4578 }
4579 }
4580 else
4581 safe_call1 (fn, pos);
4582 }
4583 }
4584
4585 it->f->inhibit_clear_image_cache = saved_inhibit_flag;
4586 unbind_to (count, Qnil);
4587
4588
4589
4590
4591
4592
4593
4594
4595 if (obuf == current_buffer)
4596 {
4597 if (begv == BEGV && zv == ZV)
4598 current_buffer->clip_changed = old_clip_changed;
4599 }
4600
4601
4602 else if (BUFFER_LIVE_P (obuf))
4603 set_buffer_internal_1 (obuf);
4604
4605
4606
4607
4608
4609
4610 it->end_charpos = ZV;
4611
4612
4613
4614
4615 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
4616 handled = HANDLED_RECOMPUTE_PROPS;
4617 }
4618
4619 return handled;
4620 }
4621
4622
4623
4624
4625
4626
4627
4628 static int
4629 face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
4630 {
4631 ptrdiff_t next_stop;
4632
4633 if (!STRINGP (it->string))
4634 {
4635 return face_at_buffer_position (it->w,
4636 IT_CHARPOS (*it),
4637 &next_stop,
4638 (IT_CHARPOS (*it)
4639 + TEXT_PROP_DISTANCE_LIMIT),
4640 false, it->base_face_id,
4641 attr_filter);
4642 }
4643 else
4644 {
4645 int base_face_id;
4646 ptrdiff_t bufpos;
4647 int i;
4648 Lisp_Object from_overlay
4649 = (it->current.overlay_string_index >= 0
4650 ? it->string_overlays[it->current.overlay_string_index
4651 % OVERLAY_STRING_CHUNK_SIZE]
4652 : Qnil);
4653
4654
4655
4656
4657
4658
4659
4660 if (! NILP (from_overlay))
4661 for (i = it->sp - 1; i >= 0; i--)
4662 {
4663 if (it->stack[i].current.overlay_string_index >= 0)
4664 from_overlay
4665 = it->string_overlays[it->stack[i].current.overlay_string_index
4666 % OVERLAY_STRING_CHUNK_SIZE];
4667 else if (! NILP (it->stack[i].from_overlay))
4668 from_overlay = it->stack[i].from_overlay;
4669
4670 if (!NILP (from_overlay))
4671 break;
4672 }
4673
4674 if (! NILP (from_overlay))
4675 {
4676 bufpos = IT_CHARPOS (*it);
4677
4678
4679 base_face_id
4680 = face_for_overlay_string (it->w,
4681 IT_CHARPOS (*it),
4682 &next_stop,
4683 (IT_CHARPOS (*it)
4684 + TEXT_PROP_DISTANCE_LIMIT),
4685 false,
4686 from_overlay, attr_filter);
4687 }
4688 else
4689 {
4690 bufpos = 0;
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708 base_face_id = it->string_from_prefix_prop_p
4709 ? (!NILP (Vface_remapping_alist)
4710 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4711 : DEFAULT_FACE_ID)
4712 : underlying_face_id (it);
4713 }
4714
4715 return face_at_string_position (it->w,
4716 it->string,
4717 IT_STRING_CHARPOS (*it),
4718 bufpos,
4719 &next_stop,
4720 base_face_id, false,
4721 attr_filter);
4722 }
4723 }
4724
4725
4726
4727
4728 static enum prop_handled
4729 handle_face_prop (struct it *it)
4730 {
4731 specpdl_ref count = SPECPDL_INDEX ();
4732
4733
4734
4735 specbind (Qinhibit_quit, Qt);
4736 const int new_face_id = face_at_pos (it, 0);
4737 unbind_to (count, Qnil);
4738
4739
4740
4741
4742
4743
4744
4745
4746 if (new_face_id != it->face_id)
4747 {
4748 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
4749
4750
4751
4752 struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
4753
4754
4755
4756
4757 if (!STRINGP (it->string)
4758 && !old_face
4759 && IT_CHARPOS (*it) > BEG)
4760 {
4761 const int prev_face_id = face_before_it_pos (it);
4762
4763 old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
4764 }
4765
4766
4767
4768
4769 it->face_id = new_face_id;
4770
4771
4772 if (!(it->start_of_box_run_p && old_face && old_face->box))
4773 it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
4774 && (old_face == NULL || !old_face->box));
4775 it->face_box_p = new_face->box != FACE_NO_BOX;
4776 }
4777
4778 return HANDLED_NORMALLY;
4779 }
4780
4781
4782
4783
4784
4785
4786
4787 static int
4788 underlying_face_id (const struct it *it)
4789 {
4790 int face_id = it->base_face_id, i;
4791
4792 eassert (STRINGP (it->string));
4793
4794 for (i = it->sp - 1; i >= 0; --i)
4795 if (NILP (it->stack[i].string))
4796 face_id = it->stack[i].face_id;
4797
4798 return face_id;
4799 }
4800
4801
4802
4803
4804
4805
4806
4807 static int
4808 face_before_or_after_it_pos (struct it *it, bool before_p)
4809 {
4810 int face_id, limit;
4811 ptrdiff_t next_check_charpos;
4812 struct it it_copy;
4813 void *it_copy_data = NULL;
4814
4815 eassert (it->s == NULL);
4816
4817 if (STRINGP (it->string))
4818 {
4819 ptrdiff_t bufpos, charpos;
4820 int base_face_id;
4821
4822
4823
4824
4825
4826 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
4827 || (IT_STRING_CHARPOS (*it) == 0 && before_p)
4828 || it->current_x <= it->first_visible_x)
4829 return it->face_id;
4830
4831 if (!it->bidi_p)
4832 {
4833
4834
4835
4836 if (before_p)
4837 charpos = IT_STRING_CHARPOS (*it) - 1;
4838 else if (it->what == IT_COMPOSITION)
4839
4840
4841 charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars;
4842 else
4843 charpos = IT_STRING_CHARPOS (*it) + 1;
4844 }
4845 else
4846 {
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857 SAVE_IT (it_copy, *it, it_copy_data);
4858 IT_STRING_CHARPOS (it_copy) = 0;
4859 bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
4860 it_copy.bidi_it.scan_dir = 0;
4861
4862 do
4863 {
4864 charpos = it_copy.bidi_it.charpos;
4865 if (charpos >= SCHARS (it->string))
4866 break;
4867 bidi_move_to_visually_next (&it_copy.bidi_it);
4868 }
4869 while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
4870
4871 if (!before_p)
4872 {
4873
4874
4875
4876 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4877
4878
4879
4880 if (it_copy.bidi_it.first_elt)
4881 n++;
4882 while (n--)
4883 bidi_move_to_visually_next (&it_copy.bidi_it);
4884
4885 charpos = it_copy.bidi_it.charpos;
4886 }
4887
4888 RESTORE_IT (it, it, it_copy_data);
4889 }
4890 eassert (0 <= charpos && charpos <= SCHARS (it->string));
4891
4892 if (it->current.overlay_string_index >= 0)
4893 bufpos = IT_CHARPOS (*it);
4894 else
4895 bufpos = 0;
4896
4897 base_face_id = underlying_face_id (it);
4898
4899
4900 face_id = face_at_string_position (it->w, it->string, charpos,
4901 bufpos, &next_check_charpos,
4902 base_face_id, false, 0);
4903
4904
4905
4906
4907 if (STRING_MULTIBYTE (it->string))
4908 {
4909 struct text_pos pos1 = string_pos (charpos, it->string);
4910 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1);
4911 struct face *face = FACE_FROM_ID (it->f, face_id);
4912 int len, c = check_char_and_length (p, &len);
4913 face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string);
4914 }
4915 }
4916 else
4917 {
4918 struct text_pos pos;
4919
4920 if ((IT_CHARPOS (*it) >= ZV && !before_p)
4921 || (IT_CHARPOS (*it) <= BEGV && before_p))
4922 return it->face_id;
4923
4924 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
4925 pos = it->current.pos;
4926
4927 if (!it->bidi_p)
4928 {
4929 if (before_p)
4930 DEC_TEXT_POS (pos, it->multibyte_p);
4931 else
4932 {
4933 if (it->what == IT_COMPOSITION)
4934 {
4935
4936
4937 pos.charpos += it->cmp_it.nchars;
4938 pos.bytepos += it->len;
4939 }
4940 else
4941 INC_TEXT_POS (pos, it->multibyte_p);
4942 }
4943 }
4944 else
4945 {
4946 if (before_p)
4947 {
4948 int current_x;
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959 if (it->current_x <= it->first_visible_x)
4960 return it->face_id;
4961 SAVE_IT (it_copy, *it, it_copy_data);
4962
4963
4964
4965
4966
4967 current_x = it_copy.current_x;
4968 move_it_vertically_backward (&it_copy, 0);
4969 move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
4970 pos = it_copy.current.pos;
4971 RESTORE_IT (it, it, it_copy_data);
4972 }
4973 else
4974 {
4975
4976
4977
4978 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4979
4980 it_copy = *it;
4981
4982
4983
4984 if (it->bidi_it.first_elt)
4985 n++;
4986 while (n--)
4987 bidi_move_to_visually_next (&it_copy.bidi_it);
4988
4989 SET_TEXT_POS (pos,
4990 it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
4991 }
4992 }
4993 eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
4994
4995
4996 face_id = face_at_buffer_position (it->w,
4997 CHARPOS (pos),
4998 &next_check_charpos,
4999 limit, false, -1, 0);
5000
5001
5002
5003
5004 if (it->multibyte_p)
5005 {
5006 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
5007 struct face *face = FACE_FROM_ID (it->f, face_id);
5008 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
5009 }
5010 }
5011
5012 return face_id;
5013 }
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024 static enum prop_handled
5025 handle_invisible_prop (struct it *it)
5026 {
5027 enum prop_handled handled = HANDLED_NORMALLY;
5028 int invis;
5029 Lisp_Object prop;
5030
5031 if (STRINGP (it->string))
5032 {
5033 Lisp_Object end_charpos, limit;
5034
5035
5036
5037
5038 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
5039 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5040 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5041
5042 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5043 {
5044
5045
5046 bool display_ellipsis_p = (invis == 2);
5047 ptrdiff_t len, endpos;
5048
5049 handled = HANDLED_RECOMPUTE_PROPS;
5050
5051
5052
5053 endpos = len = SCHARS (it->string);
5054 XSETINT (limit, len);
5055 do
5056 {
5057 end_charpos
5058 = Fnext_single_property_change (end_charpos, Qinvisible,
5059 it->string, limit);
5060
5061
5062 eassert (FIXNUMP (end_charpos));
5063 if (FIXNUMP (end_charpos))
5064 {
5065 endpos = XFIXNAT (end_charpos);
5066 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5067 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5068 if (invis == 2)
5069 display_ellipsis_p = true;
5070 }
5071 else
5072 endpos = len;
5073 }
5074 while (invis != 0 && endpos < len);
5075
5076 if (display_ellipsis_p)
5077 it->ellipsis_p = true;
5078
5079 if (endpos < len)
5080 {
5081
5082 struct text_pos old;
5083 ptrdiff_t oldpos;
5084
5085 old = it->current.string_pos;
5086 oldpos = CHARPOS (old);
5087 if (it->bidi_p)
5088 {
5089 if (it->bidi_it.first_elt
5090 && it->bidi_it.charpos < SCHARS (it->string))
5091 bidi_paragraph_init (it->paragraph_embedding,
5092 &it->bidi_it, true);
5093
5094 do
5095 {
5096 bidi_move_to_visually_next (&it->bidi_it);
5097 }
5098 while (oldpos <= it->bidi_it.charpos
5099 && it->bidi_it.charpos < endpos
5100 && it->bidi_it.charpos < it->bidi_it.string.schars);
5101
5102 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5103 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5104 if (IT_CHARPOS (*it) >= endpos)
5105 it->prev_stop = endpos;
5106 }
5107 else
5108 {
5109 IT_STRING_CHARPOS (*it) = endpos;
5110 compute_string_pos (&it->current.string_pos, old, it->string);
5111 }
5112 }
5113 else
5114 {
5115
5116
5117
5118 if (it->current.overlay_string_index >= 0
5119 && !display_ellipsis_p)
5120 {
5121 next_overlay_string (it);
5122
5123
5124 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5125 }
5126 else
5127 {
5128 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
5129 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5130 }
5131 }
5132 }
5133 }
5134 else
5135 {
5136 ptrdiff_t newpos, next_stop, start_charpos, tem;
5137 Lisp_Object pos, overlay;
5138
5139
5140 tem = start_charpos = IT_CHARPOS (*it);
5141 pos = make_fixnum (tem);
5142 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5143 &overlay);
5144 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5145
5146
5147 if (invis != 0 && start_charpos < it->end_charpos)
5148 {
5149
5150
5151 bool display_ellipsis_p = invis == 2;
5152
5153 handled = HANDLED_RECOMPUTE_PROPS;
5154
5155
5156
5157 do
5158 {
5159
5160
5161
5162
5163
5164 newpos = skip_invisible (tem, &next_stop, ZV, it->window);
5165
5166
5167
5168
5169 if (newpos == tem || newpos >= ZV)
5170 invis = 0;
5171 else
5172 {
5173
5174
5175
5176
5177
5178
5179 pos = make_fixnum (newpos);
5180 prop = Fget_char_property (pos, Qinvisible, it->window);
5181 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5182 }
5183
5184
5185
5186 if (invis != 0)
5187 tem = next_stop;
5188
5189
5190
5191 if (invis == 2)
5192 display_ellipsis_p = true;
5193 }
5194 while (invis != 0);
5195
5196
5197 if (it->bidi_p)
5198 {
5199 ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
5200 bool on_newline
5201 = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
5202 bool after_newline
5203 = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
5204
5205
5206
5207
5208
5209
5210
5211
5212 if (on_newline || after_newline)
5213 {
5214 struct text_pos tpos;
5215 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
5216
5217 SET_TEXT_POS (tpos, newpos, bpos);
5218 reseat_1 (it, tpos, false);
5219
5220
5221
5222
5223
5224 if (on_newline)
5225 {
5226 it->bidi_it.first_elt = false;
5227 it->bidi_it.paragraph_dir = pdir;
5228 it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
5229 it->bidi_it.nchars = 1;
5230 it->bidi_it.ch_len = 1;
5231 }
5232 }
5233 else
5234 {
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5246 {
5247
5248
5249
5250
5251
5252
5253
5254 bidi_paragraph_init (it->paragraph_embedding,
5255 &it->bidi_it, true);
5256 }
5257 do
5258 {
5259 bidi_move_to_visually_next (&it->bidi_it);
5260 }
5261 while (it->stop_charpos <= it->bidi_it.charpos
5262 && it->bidi_it.charpos < newpos);
5263 IT_CHARPOS (*it) = it->bidi_it.charpos;
5264 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5265
5266
5267
5268
5269 if (IT_CHARPOS (*it) >= newpos)
5270 it->prev_stop = newpos;
5271 }
5272 }
5273 else
5274 {
5275 IT_CHARPOS (*it) = newpos;
5276 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
5277 }
5278
5279 if (display_ellipsis_p)
5280 {
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293 if (!STRINGP (it->object))
5294 {
5295 it->position.charpos = newpos - 1;
5296 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5297 }
5298 }
5299
5300
5301
5302
5303
5304
5305
5306 if (NILP (overlay)
5307 && get_overlay_strings (it, it->stop_charpos))
5308 {
5309 handled = HANDLED_RECOMPUTE_PROPS;
5310 if (it->sp > 0)
5311 {
5312 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325 it->stack[it->sp - 1].stop_charpos
5326 = CHARPOS (it->stack[it->sp - 1].current.pos);
5327 }
5328 }
5329 else if (display_ellipsis_p)
5330 {
5331 it->ellipsis_p = true;
5332
5333
5334
5335 handled = HANDLED_RETURN;
5336 }
5337 }
5338 }
5339
5340 return handled;
5341 }
5342
5343
5344
5345
5346
5347 static void
5348 setup_for_ellipsis (struct it *it, int len)
5349 {
5350
5351
5352 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5353 {
5354 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5355 it->dpvec = v->contents;
5356 it->dpend = v->contents + v->header.size;
5357 }
5358 else
5359 {
5360
5361 it->dpvec = default_invis_vector;
5362 it->dpend = default_invis_vector + 3;
5363 }
5364
5365 it->dpvec_char_len = len;
5366 it->current.dpvec_index = 0;
5367 it->dpvec_face_id = -1;
5368
5369
5370
5371
5372
5373
5374
5375
5376 if (it->saved_face_id >= 0)
5377 it->face_id = it->saved_face_id;
5378
5379
5380
5381 if (it->method == GET_FROM_BUFFER)
5382 it->ignore_overlay_strings_at_pos_p = false;
5383
5384 it->method = GET_FROM_DISPLAY_VECTOR;
5385 it->ellipsis_p = true;
5386 }
5387
5388
5389 static Lisp_Object
5390 find_display_property (Lisp_Object disp, Lisp_Object prop)
5391 {
5392 if (NILP (disp))
5393 return Qnil;
5394
5395 if (VECTORP (disp))
5396 {
5397 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5398 {
5399 Lisp_Object elem = AREF (disp, i);
5400 if (CONSP (elem)
5401 && CONSP (XCDR (elem))
5402 && EQ (XCAR (elem), prop))
5403 return XCAR (XCDR (elem));
5404 }
5405 return Qnil;
5406 }
5407
5408 else if (CONSP (disp)
5409 && CONSP (XCAR (disp)))
5410 {
5411 while (!NILP (disp))
5412 {
5413 Lisp_Object elem = XCAR (disp);
5414 if (CONSP (elem)
5415 && CONSP (XCDR (elem))
5416 && EQ (XCAR (elem), prop))
5417 return XCAR (XCDR (elem));
5418
5419
5420
5421 if (CONSP (XCDR (disp)))
5422 disp = XCDR (disp);
5423 else
5424 disp = Qnil;
5425 }
5426 return Qnil;
5427 }
5428
5429 else if (CONSP (disp)
5430 && CONSP (XCDR (disp))
5431 && EQ (XCAR (disp), prop))
5432 return XCAR (XCDR (disp));
5433 else
5434 return Qnil;
5435 }
5436
5437 static Lisp_Object
5438 get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object)
5439 {
5440 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5441 Qdisplay, object),
5442 prop);
5443 }
5444
5445 static void
5446 display_min_width (struct it *it, ptrdiff_t bufpos,
5447 Lisp_Object object, Lisp_Object width_spec)
5448 {
5449
5450
5451 if (!NILP (it->min_width_property)
5452 && !EQ (width_spec, it->min_width_property))
5453 {
5454 if (!it->glyph_row)
5455 return;
5456
5457
5458
5459
5460
5461 if ((bufpos == 0
5462 && !EQ (it->min_width_property,
5463 get_display_property (0, Qmin_width, object)))
5464
5465
5466 || (bufpos > BEGV
5467 && EQ (it->min_width_property,
5468 get_display_property (bufpos - 1, Qmin_width, object))))
5469 {
5470 Lisp_Object w = Qnil;
5471 double width;
5472 #ifdef HAVE_WINDOW_SYSTEM
5473 if (FRAME_WINDOW_P (it->f))
5474 {
5475 struct font *font = NULL;
5476 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5477 font = face->font ? face->font : FRAME_FONT (it->f);
5478 calc_pixel_width_or_height (&width, it,
5479 XCAR (it->min_width_property),
5480 font, true, NULL);
5481 width -= it->current_x - it->min_width_start;
5482 w = list1 (make_int (width));
5483 }
5484 else
5485 #endif
5486 {
5487 calc_pixel_width_or_height (&width, it,
5488 XCAR (it->min_width_property),
5489 NULL, true, NULL);
5490 width -= (it->current_x - it->min_width_start) /
5491 FRAME_COLUMN_WIDTH (it->f);
5492 w = make_int (width);
5493 }
5494
5495
5496 it->object = list3 (Qspace, QCwidth, w);
5497 produce_stretch_glyph (it);
5498 if (it->area == TEXT_AREA)
5499 it->current_x += it->pixel_width;
5500 it->min_width_property = Qnil;
5501 }
5502 }
5503
5504
5505
5506
5507 if (CONSP (width_spec))
5508 {
5509 if (bufpos == BEGV
5510
5511 || (bufpos == 0
5512 && !EQ (it->min_width_property,
5513 get_display_property (0, Qmin_width, object)))
5514
5515 || (bufpos > BEGV
5516 && !EQ (width_spec,
5517 get_display_property (bufpos - 1, Qmin_width, object))))
5518 {
5519 it->min_width_property = width_spec;
5520 it->min_width_start = it->current_x;
5521 }
5522 }
5523 }
5524
5525 DEFUN ("get-display-property", Fget_display_property,
5526 Sget_display_property, 2, 4, 0,
5527 doc:
5528
5529
5530
5531
5532 )
5533 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5534 Lisp_Object properties)
5535 {
5536 if (NILP (properties))
5537 properties = Fget_text_property (position, Qdisplay, object);
5538 else
5539 CHECK_LIST (properties);
5540
5541 return find_display_property (properties, prop);
5542 }
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556 static enum prop_handled
5557 handle_display_prop (struct it *it)
5558 {
5559 Lisp_Object propval, object, overlay;
5560 struct text_pos *position;
5561 ptrdiff_t bufpos;
5562
5563 int display_replaced = 0;
5564
5565 if (STRINGP (it->string))
5566 {
5567 object = it->string;
5568 position = &it->current.string_pos;
5569 bufpos = CHARPOS (it->current.pos);
5570 }
5571 else
5572 {
5573 XSETWINDOW (object, it->w);
5574 position = &it->current.pos;
5575 bufpos = CHARPOS (*position);
5576 }
5577
5578
5579 it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
5580 it->space_width = Qnil;
5581 it->font_height = Qnil;
5582 it->voffset = 0;
5583
5584
5585
5586
5587 if (!it->string_from_display_prop_p)
5588 it->area = TEXT_AREA;
5589
5590 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5591 Qdisplay, object, &overlay);
5592
5593
5594 if (!STRINGP (it->string))
5595 object = it->w->contents;
5596
5597
5598 if (!NILP (it->min_width_property)
5599 && NILP (find_display_property (propval, Qmin_width)))
5600 display_min_width (it, bufpos, object, Qnil);
5601
5602 if (NILP (propval))
5603 return HANDLED_NORMALLY;
5604
5605
5606
5607 display_replaced = handle_display_spec (it, propval, object, overlay,
5608 position, bufpos,
5609 FRAME_WINDOW_P (it->f));
5610 return display_replaced != 0 ? HANDLED_RETURN : HANDLED_NORMALLY;
5611 }
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629 static int
5630 handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5631 Lisp_Object overlay, struct text_pos *position,
5632 ptrdiff_t bufpos, bool frame_window_p)
5633 {
5634 int replacing = 0;
5635 bool enable_eval = true;
5636
5637
5638 if (CONSP (spec) && EQ (XCAR (spec), Qdisable_eval))
5639 {
5640 enable_eval = false;
5641 spec = CONSP (XCDR (spec)) ? XCAR (XCDR (spec)) : Qnil;
5642 }
5643
5644 if (CONSP (spec)
5645
5646 && !EQ (XCAR (spec), Qimage)
5647 #ifdef HAVE_XWIDGETS
5648 && !EQ (XCAR (spec), Qxwidget)
5649 #endif
5650 && !EQ (XCAR (spec), Qspace)
5651 && !EQ (XCAR (spec), Qwhen)
5652 && !EQ (XCAR (spec), Qslice)
5653 && !EQ (XCAR (spec), Qspace_width)
5654 && !EQ (XCAR (spec), Qheight)
5655 && !EQ (XCAR (spec), Qraise)
5656
5657 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5658 && !EQ (XCAR (spec), Qleft_fringe)
5659 && !EQ (XCAR (spec), Qright_fringe)
5660 && !EQ (XCAR (spec), Qmin_width)
5661 && !NILP (XCAR (spec)))
5662 {
5663 for (; CONSP (spec); spec = XCDR (spec))
5664 {
5665 int rv = handle_single_display_spec (it, XCAR (spec), object,
5666 overlay, position, bufpos,
5667 replacing, frame_window_p,
5668 enable_eval);
5669 if (rv != 0)
5670 {
5671 replacing = rv;
5672
5673
5674 if (!it || STRINGP (object))
5675 break;
5676 }
5677 }
5678 }
5679 else if (VECTORP (spec))
5680 {
5681 ptrdiff_t i;
5682 for (i = 0; i < ASIZE (spec); ++i)
5683 {
5684 int rv = handle_single_display_spec (it, AREF (spec, i), object,
5685 overlay, position, bufpos,
5686 replacing, frame_window_p,
5687 enable_eval);
5688 if (rv != 0)
5689 {
5690 replacing = rv;
5691
5692
5693 if (!it || STRINGP (object))
5694 break;
5695 }
5696 }
5697 }
5698 else
5699 replacing = handle_single_display_spec (it, spec, object, overlay, position,
5700 bufpos, 0, frame_window_p,
5701 enable_eval);
5702 return replacing;
5703 }
5704
5705
5706
5707
5708 static struct text_pos
5709 display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
5710 {
5711 Lisp_Object end;
5712 struct text_pos end_pos;
5713
5714 end = Fnext_single_char_property_change (make_fixnum (CHARPOS (start_pos)),
5715 Qdisplay, object, Qnil);
5716 CHARPOS (end_pos) = XFIXNAT (end);
5717 if (STRINGP (object))
5718 compute_string_pos (&end_pos, start_pos, it->string);
5719 else
5720 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFIXNAT (end));
5721
5722 return end_pos;
5723 }
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751 static int
5752 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5753 Lisp_Object overlay, struct text_pos *position,
5754 ptrdiff_t bufpos, int display_replaced,
5755 bool frame_window_p, bool enable_eval_p)
5756 {
5757 Lisp_Object form;
5758 Lisp_Object location, value;
5759 struct text_pos start_pos = *position;
5760 void *itdata = NULL;
5761
5762
5763
5764 form = Qt;
5765 if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
5766 {
5767 spec = XCDR (spec);
5768 if (!CONSP (spec))
5769 return 0;
5770 form = XCAR (spec);
5771 spec = XCDR (spec);
5772 }
5773
5774 if (!NILP (form) && !EQ (form, Qt) && !enable_eval_p)
5775 form = Qnil;
5776 if (!NILP (form) && !EQ (form, Qt))
5777 {
5778 specpdl_ref count = SPECPDL_INDEX ();
5779
5780
5781
5782
5783
5784
5785 if (NILP (object))
5786 XSETBUFFER (object, current_buffer);
5787 specbind (Qobject, object);
5788 specbind (Qposition, make_fixnum (CHARPOS (*position)));
5789 specbind (Qbuffer_position, make_fixnum (bufpos));
5790
5791
5792 itdata = bidi_shelve_cache ();
5793 form = safe_eval (form);
5794 bidi_unshelve_cache (itdata, false);
5795 form = unbind_to (count, form);
5796 }
5797
5798 if (NILP (form))
5799 return 0;
5800
5801
5802 if (CONSP (spec)
5803 && EQ (XCAR (spec), Qheight)
5804 && CONSP (XCDR (spec)))
5805 {
5806 if (it)
5807 {
5808 if (!FRAME_WINDOW_P (it->f))
5809 return 0;
5810
5811 it->font_height = XCAR (XCDR (spec));
5812 if (!NILP (it->font_height))
5813 {
5814 int new_height = -1;
5815
5816 if (CONSP (it->font_height)
5817 && (EQ (XCAR (it->font_height), Qplus)
5818 || EQ (XCAR (it->font_height), Qminus))
5819 && CONSP (XCDR (it->font_height))
5820 && RANGED_FIXNUMP (0, XCAR (XCDR (it->font_height)), INT_MAX))
5821 {
5822
5823 int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
5824 if (EQ (XCAR (it->font_height), Qplus))
5825 steps = - steps;
5826 it->face_id = smaller_face (it->f, it->face_id, steps);
5827 }
5828 else if (FUNCTIONP (it->font_height) && enable_eval_p)
5829 {
5830
5831
5832 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5833 Lisp_Object height;
5834 itdata = bidi_shelve_cache ();
5835 height = safe_call1 (it->font_height,
5836 face->lface[LFACE_HEIGHT_INDEX]);
5837 bidi_unshelve_cache (itdata, false);
5838 if (NUMBERP (height))
5839 new_height = XFLOATINT (height);
5840 }
5841 else if (NUMBERP (it->font_height))
5842 {
5843
5844 struct face *f;
5845
5846 f = FACE_FROM_ID (it->f,
5847 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
5848 new_height = (XFLOATINT (it->font_height)
5849 * XFIXNUM (f->lface[LFACE_HEIGHT_INDEX]));
5850 }
5851 else if (enable_eval_p)
5852 {
5853
5854
5855 specpdl_ref count = SPECPDL_INDEX ();
5856 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5857
5858 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
5859 itdata = bidi_shelve_cache ();
5860 value = safe_eval (it->font_height);
5861 bidi_unshelve_cache (itdata, false);
5862 value = unbind_to (count, value);
5863
5864 if (NUMBERP (value))
5865 new_height = XFLOATINT (value);
5866 }
5867
5868 if (new_height > 0)
5869 it->face_id = face_with_height (it->f, it->face_id, new_height);
5870 }
5871 }
5872
5873 return 0;
5874 }
5875
5876
5877 if (CONSP (spec)
5878 && EQ (XCAR (spec), Qspace_width)
5879 && CONSP (XCDR (spec)))
5880 {
5881 if (it)
5882 {
5883 if (!FRAME_WINDOW_P (it->f))
5884 return 0;
5885
5886 value = XCAR (XCDR (spec));
5887 if (NUMBERP (value) && XFLOATINT (value) > 0)
5888 it->space_width = value;
5889 }
5890
5891 return 0;
5892 }
5893
5894
5895 if (CONSP (spec)
5896 && EQ (XCAR (spec), Qmin_width)
5897 && CONSP (XCDR (spec))
5898 && CONSP (XCAR (XCDR (spec))))
5899 {
5900 if (it)
5901 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5902 return 0;
5903 }
5904
5905
5906 if (CONSP (spec)
5907 && EQ (XCAR (spec), Qslice))
5908 {
5909 Lisp_Object tem;
5910
5911 if (it)
5912 {
5913 if (!FRAME_WINDOW_P (it->f))
5914 return 0;
5915
5916 if (tem = XCDR (spec), CONSP (tem))
5917 {
5918 it->slice.x = XCAR (tem);
5919 if (tem = XCDR (tem), CONSP (tem))
5920 {
5921 it->slice.y = XCAR (tem);
5922 if (tem = XCDR (tem), CONSP (tem))
5923 {
5924 it->slice.width = XCAR (tem);
5925 if (tem = XCDR (tem), CONSP (tem))
5926 it->slice.height = XCAR (tem);
5927 }
5928 }
5929 }
5930 }
5931
5932 return 0;
5933 }
5934
5935
5936 if (CONSP (spec)
5937 && EQ (XCAR (spec), Qraise)
5938 && CONSP (XCDR (spec)))
5939 {
5940 if (it)
5941 {
5942 if (!FRAME_WINDOW_P (it->f))
5943 return 0;
5944
5945 #ifdef HAVE_WINDOW_SYSTEM
5946 value = XCAR (XCDR (spec));
5947 if (NUMBERP (value))
5948 {
5949 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5950 it->voffset = - (XFLOATINT (value)
5951 * (normal_char_height (face->font, -1)));
5952 }
5953 #endif
5954 }
5955
5956 return 0;
5957 }
5958
5959
5960
5961 if (it && it->string_from_display_prop_p)
5962 return 0;
5963
5964
5965
5966 if (it)
5967 {
5968 start_pos = *position;
5969 *position = display_prop_end (it, object, start_pos);
5970
5971
5972
5973
5974
5975
5976
5977 if (!NILP (overlay))
5978 {
5979 ptrdiff_t ovendpos = OVERLAY_END (overlay);
5980
5981
5982
5983
5984
5985
5986
5987 ovendpos = clip_to_bounds (BEGV, ovendpos, ZV);
5988
5989 if (ovendpos > CHARPOS (*position))
5990 SET_TEXT_POS (*position, ovendpos, CHAR_TO_BYTE (ovendpos));
5991 }
5992 }
5993 value = Qnil;
5994
5995
5996
5997 if (it)
5998 it->stop_charpos = position->charpos;
5999
6000
6001
6002 if (CONSP (spec)
6003 && (EQ (XCAR (spec), Qleft_fringe)
6004 || EQ (XCAR (spec), Qright_fringe))
6005 && CONSP (XCDR (spec)))
6006 {
6007 if (it)
6008 {
6009 if (!FRAME_WINDOW_P (it->f))
6010
6011
6012 {
6013
6014
6015
6016
6017 if (it->bidi_p)
6018 {
6019 it->position = *position;
6020 iterate_out_of_display_property (it);
6021 *position = it->position;
6022 }
6023 return 1;
6024 }
6025 }
6026 else if (!frame_window_p)
6027 return 1;
6028
6029 #ifdef HAVE_WINDOW_SYSTEM
6030 value = XCAR (XCDR (spec));
6031 int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
6032 if (! fringe_bitmap)
6033
6034
6035 {
6036 if (it && it->bidi_p)
6037 {
6038 it->position = *position;
6039 iterate_out_of_display_property (it);
6040 *position = it->position;
6041 }
6042 return 1;
6043 }
6044
6045 if (it)
6046 {
6047 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
6048
6049 if (CONSP (XCDR (XCDR (spec))))
6050 {
6051 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
6052 int face_id2;
6053
6054
6055
6056 specpdl_ref count1 = SPECPDL_INDEX ();
6057 specbind (Qinhibit_quit, Qt);
6058 face_id2 = lookup_derived_face (it->w, it->f, face_name,
6059 FRINGE_FACE_ID, false);
6060 unbind_to (count1, Qnil);
6061 if (face_id2 >= 0)
6062 face_id = face_id2;
6063 }
6064
6065
6066
6067 push_it (it, position);
6068
6069 it->area = TEXT_AREA;
6070 it->what = IT_IMAGE;
6071 it->image_id = -1;
6072 it->position = start_pos;
6073 it->object = NILP (object) ? it->w->contents : object;
6074 it->method = GET_FROM_IMAGE;
6075 it->from_overlay = Qnil;
6076 it->face_id = face_id;
6077 it->from_disp_prop_p = true;
6078
6079
6080
6081
6082 *position = start_pos;
6083
6084 if (EQ (XCAR (spec), Qleft_fringe))
6085 {
6086 it->left_user_fringe_bitmap = fringe_bitmap;
6087 it->left_user_fringe_face_id = face_id;
6088 }
6089 else
6090 {
6091 it->right_user_fringe_bitmap = fringe_bitmap;
6092 it->right_user_fringe_face_id = face_id;
6093 }
6094 }
6095 #endif
6096 return 1;
6097 }
6098
6099
6100
6101
6102 location = Qunbound;
6103 if (CONSP (spec) && CONSP (XCAR (spec)))
6104 {
6105 Lisp_Object tem;
6106
6107 value = XCDR (spec);
6108 if (CONSP (value))
6109 value = XCAR (value);
6110
6111 tem = XCAR (spec);
6112 if (EQ (XCAR (tem), Qmargin)
6113 && (tem = XCDR (tem),
6114 tem = CONSP (tem) ? XCAR (tem) : Qnil,
6115 (NILP (tem)
6116 || EQ (tem, Qleft_margin)
6117 || EQ (tem, Qright_margin))))
6118 location = tem;
6119 }
6120
6121 if (BASE_EQ (location, Qunbound))
6122 {
6123 location = Qnil;
6124 value = spec;
6125 }
6126
6127
6128
6129
6130
6131
6132
6133
6134 bool valid_p = (STRINGP (value)
6135 #ifdef HAVE_WINDOW_SYSTEM
6136 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6137 && valid_image_p (value))
6138 #endif
6139 || (CONSP (value) && EQ (XCAR (value), Qspace))
6140 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6141 && valid_xwidget_spec_p (value)));
6142
6143 if (valid_p && display_replaced == 0)
6144 {
6145 int retval = 1;
6146
6147 if (!it)
6148 {
6149
6150
6151
6152 if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
6153 retval = 2;
6154 return retval;
6155 }
6156
6157
6158
6159 push_it (it, position);
6160 it->from_overlay = overlay;
6161 it->from_disp_prop_p = true;
6162
6163 if (NILP (location))
6164 it->area = TEXT_AREA;
6165 else if (EQ (location, Qleft_margin))
6166 it->area = LEFT_MARGIN_AREA;
6167 else
6168 it->area = RIGHT_MARGIN_AREA;
6169
6170 if (STRINGP (value))
6171 {
6172 it->string = value;
6173 it->multibyte_p = STRING_MULTIBYTE (it->string);
6174 it->current.overlay_string_index = -1;
6175 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6176 it->end_charpos = it->string_nchars = SCHARS (it->string);
6177 it->method = GET_FROM_STRING;
6178 it->stop_charpos = 0;
6179 it->prev_stop = 0;
6180 it->base_level_stop = 0;
6181 it->string_from_display_prop_p = true;
6182 it->cmp_it.id = -1;
6183
6184
6185
6186 if (BUFFERP (object))
6187 *position = start_pos;
6188
6189
6190
6191
6192 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6193 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6194 else
6195 it->paragraph_embedding = L2R;
6196
6197
6198 if (it->bidi_p)
6199 {
6200 it->bidi_it.string.lstring = it->string;
6201 it->bidi_it.string.s = NULL;
6202 it->bidi_it.string.schars = it->end_charpos;
6203 it->bidi_it.string.bufpos = bufpos;
6204 it->bidi_it.string.from_disp_str = true;
6205 it->bidi_it.string.unibyte = !it->multibyte_p;
6206 it->bidi_it.w = it->w;
6207 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6208 }
6209 }
6210 else if (CONSP (value) && EQ (XCAR (value), Qspace))
6211 {
6212 it->method = GET_FROM_STRETCH;
6213 it->object = value;
6214 *position = it->position = start_pos;
6215 retval = 1 + (it->area == TEXT_AREA);
6216 }
6217 else if (valid_xwidget_spec_p (value))
6218 {
6219 it->what = IT_XWIDGET;
6220 it->method = GET_FROM_XWIDGET;
6221 it->position = start_pos;
6222 it->object = NILP (object) ? it->w->contents : object;
6223 *position = start_pos;
6224 it->xwidget = lookup_xwidget (value);
6225 }
6226 #ifdef HAVE_WINDOW_SYSTEM
6227 else
6228 {
6229 specpdl_ref count = SPECPDL_INDEX ();
6230
6231 it->what = IT_IMAGE;
6232
6233
6234
6235 specbind (Qinhibit_quit, Qt);
6236 it->image_id = lookup_image (it->f, value, it->face_id);
6237 unbind_to (count, Qnil);
6238 it->position = start_pos;
6239 it->object = NILP (object) ? it->w->contents : object;
6240 it->method = GET_FROM_IMAGE;
6241
6242
6243
6244
6245 *position = start_pos;
6246 }
6247 #endif
6248
6249 return retval;
6250 }
6251
6252
6253
6254 *position = start_pos;
6255 return 0;
6256 }
6257
6258
6259
6260
6261
6262
6263 bool
6264 display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
6265 ptrdiff_t charpos, ptrdiff_t bytepos)
6266 {
6267 bool frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
6268 struct text_pos position;
6269
6270 SET_TEXT_POS (position, charpos, bytepos);
6271 return (handle_display_spec (NULL, prop, Qnil, overlay,
6272 &position, charpos, frame_window_p)
6273 != 0);
6274 }
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285 static bool
6286 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
6287 {
6288 if (EQ (string, prop))
6289 return true;
6290
6291
6292 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
6293 {
6294 prop = XCDR (prop);
6295 if (!CONSP (prop))
6296 return false;
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307 prop = XCDR (prop);
6308 }
6309
6310 if (CONSP (prop))
6311
6312 if (EQ (XCAR (prop), Qmargin))
6313 {
6314 prop = XCDR (prop);
6315 if (!CONSP (prop))
6316 return false;
6317
6318 prop = XCDR (prop);
6319 if (!CONSP (prop))
6320 return false;
6321 }
6322
6323 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
6324 }
6325
6326
6327
6328
6329 static bool
6330 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
6331 {
6332 if (CONSP (prop)
6333 && !EQ (XCAR (prop), Qwhen)
6334 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
6335 {
6336
6337 while (CONSP (prop))
6338 {
6339 if (single_display_spec_string_p (XCAR (prop), string))
6340 return true;
6341 prop = XCDR (prop);
6342 }
6343 }
6344 else if (VECTORP (prop))
6345 {
6346
6347 ptrdiff_t i;
6348 for (i = 0; i < ASIZE (prop); ++i)
6349 if (single_display_spec_string_p (AREF (prop, i), string))
6350 return true;
6351 }
6352 else
6353 return single_display_spec_string_p (prop, string);
6354
6355 return false;
6356 }
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368 static ptrdiff_t
6369 string_buffer_position_lim (Lisp_Object string,
6370 ptrdiff_t from, ptrdiff_t to, bool back_p)
6371 {
6372 Lisp_Object limit, prop, pos;
6373 bool found = false;
6374
6375 pos = make_fixnum (max (from, BEGV));
6376
6377 if (!back_p)
6378 {
6379 limit = make_fixnum (min (to, ZV));
6380 while (!found && !EQ (pos, limit))
6381 {
6382 prop = Fget_char_property (pos, Qdisplay, Qnil);
6383 if (!NILP (prop) && display_prop_string_p (prop, string))
6384 found = true;
6385 else
6386 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
6387 limit);
6388 }
6389 }
6390 else
6391 {
6392 limit = make_fixnum (max (to, BEGV));
6393 while (!found && !EQ (pos, limit))
6394 {
6395 prop = Fget_char_property (pos, Qdisplay, Qnil);
6396 if (!NILP (prop) && display_prop_string_p (prop, string))
6397 found = true;
6398 else
6399 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
6400 limit);
6401 }
6402 }
6403
6404 return found ? XFIXNUM (pos) : 0;
6405 }
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416 static ptrdiff_t
6417 string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6418 {
6419 const int MAX_DISTANCE = 1000;
6420 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6421 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6422 forward_limit, false);
6423
6424 if (!found)
6425 {
6426 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6427 found = string_buffer_position_lim (string, around_charpos,
6428 backward_limit, true);
6429 }
6430 return found;
6431 }
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442 static enum prop_handled
6443 handle_composition_prop (struct it *it)
6444 {
6445 Lisp_Object prop, string;
6446 ptrdiff_t pos, pos_byte, start, end;
6447
6448 if (STRINGP (it->string))
6449 {
6450 unsigned char *s;
6451
6452 pos = IT_STRING_CHARPOS (*it);
6453 pos_byte = IT_STRING_BYTEPOS (*it);
6454 string = it->string;
6455 s = SDATA (string) + pos_byte;
6456 if (STRING_MULTIBYTE (string))
6457 it->c = STRING_CHAR (s);
6458 else
6459 it->c = *s;
6460 }
6461 else
6462 {
6463 pos = IT_CHARPOS (*it);
6464 pos_byte = IT_BYTEPOS (*it);
6465 string = Qnil;
6466 it->c = FETCH_CHAR (pos_byte);
6467 }
6468
6469
6470
6471
6472 if (find_composition (pos, -1, &start, &end, &prop, string)
6473 && composition_valid_p (start, end, prop)
6474 && (STRINGP (it->string) || (PT <= start || PT >= end)))
6475 {
6476 if (start < pos)
6477
6478
6479
6480 return HANDLED_NORMALLY;
6481 if (start != pos)
6482 {
6483 if (STRINGP (it->string))
6484 pos_byte = string_char_to_byte (it->string, start);
6485 else
6486 pos_byte = CHAR_TO_BYTE (start);
6487 }
6488 it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
6489 prop, string);
6490
6491 if (it->cmp_it.id >= 0)
6492 {
6493 it->cmp_it.ch = -1;
6494 it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
6495 it->cmp_it.nglyphs = -1;
6496 }
6497 }
6498
6499 return HANDLED_NORMALLY;
6500 }
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511 struct overlay_entry
6512 {
6513 Lisp_Object overlay;
6514 Lisp_Object string;
6515 EMACS_INT priority;
6516 bool after_string_p;
6517 };
6518
6519
6520
6521
6522
6523 static enum prop_handled
6524 handle_overlay_change (struct it *it)
6525 {
6526 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
6527 return HANDLED_RECOMPUTE_PROPS;
6528 else
6529 return HANDLED_NORMALLY;
6530 }
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540 static void
6541 next_overlay_string (struct it *it)
6542 {
6543 ++it->current.overlay_string_index;
6544 if (it->current.overlay_string_index == it->n_overlay_strings)
6545 {
6546
6547
6548
6549
6550 it->ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
6551 pop_it (it);
6552 eassert (it->sp > 0
6553 || (NILP (it->string)
6554 && it->method == GET_FROM_BUFFER
6555 && it->stop_charpos >= BEGV
6556 && it->stop_charpos <= it->end_charpos));
6557 it->current.overlay_string_index = -1;
6558 it->n_overlay_strings = 0;
6559
6560
6561
6562
6563 if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
6564 pop_it (it);
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574 if (it->overlay_strings_charpos == IT_CHARPOS (*it))
6575 it->ignore_overlay_strings_at_pos_p = true;
6576
6577
6578
6579
6580 if (NILP (it->string)
6581 && IT_CHARPOS (*it) >= it->end_charpos
6582 && it->overlay_strings_charpos >= it->end_charpos)
6583 it->overlay_strings_at_end_processed_p = true;
6584
6585
6586
6587
6588
6589
6590
6591 it->overlay_strings_charpos = -1;
6592 }
6593 else
6594 {
6595
6596
6597
6598
6599
6600
6601 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
6602
6603 if (it->current.overlay_string_index && i == 0)
6604 load_overlay_strings (it, it->overlay_strings_charpos);
6605
6606
6607
6608 it->string = it->overlay_strings[i];
6609 it->multibyte_p = STRING_MULTIBYTE (it->string);
6610 SET_TEXT_POS (it->current.string_pos, 0, 0);
6611 it->method = GET_FROM_STRING;
6612 it->stop_charpos = 0;
6613 it->end_charpos = SCHARS (it->string);
6614 if (it->cmp_it.stop_pos >= 0)
6615 it->cmp_it.stop_pos = 0;
6616 it->prev_stop = 0;
6617 it->base_level_stop = 0;
6618
6619
6620 if (it->bidi_p)
6621 {
6622 it->bidi_it.string.lstring = it->string;
6623 it->bidi_it.string.s = NULL;
6624 it->bidi_it.string.schars = SCHARS (it->string);
6625 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
6626 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6627 it->bidi_it.string.unibyte = !it->multibyte_p;
6628 it->bidi_it.w = it->w;
6629 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6630 }
6631 }
6632
6633 CHECK_IT (it);
6634 }
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653 static int
6654 compare_overlay_entries (const void *e1, const void *e2)
6655 {
6656 struct overlay_entry const *entry1 = e1;
6657 struct overlay_entry const *entry2 = e2;
6658 int result;
6659
6660 if (entry1->after_string_p != entry2->after_string_p)
6661 {
6662
6663
6664 if (EQ (entry1->overlay, entry2->overlay))
6665 result = entry1->after_string_p ? 1 : -1;
6666 else
6667 result = entry1->after_string_p ? -1 : 1;
6668 }
6669 else if (entry1->priority != entry2->priority)
6670 {
6671 if (entry1->after_string_p)
6672
6673 result = entry2->priority < entry1->priority ? -1 : 1;
6674 else
6675
6676 result = entry1->priority < entry2->priority ? -1 : 1;
6677 }
6678 else
6679 result = 0;
6680
6681 return result;
6682 }
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709 static void
6710 load_overlay_strings (struct it *it, ptrdiff_t charpos)
6711 {
6712 ptrdiff_t n = 0;
6713 struct overlay_entry entriesbuf[20];
6714 ptrdiff_t size = ARRAYELTS (entriesbuf);
6715 struct overlay_entry *entries = entriesbuf;
6716 struct itree_node *node;
6717
6718 USE_SAFE_ALLOCA;
6719
6720 if (charpos <= 0)
6721 charpos = IT_CHARPOS (*it);
6722
6723
6724
6725
6726
6727 #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
6728 do \
6729 { \
6730 Lisp_Object priority; \
6731 \
6732 if (n == size) \
6733 { \
6734 struct overlay_entry *old = entries; \
6735 SAFE_NALLOCA (entries, 2, size); \
6736 memcpy (entries, old, size * sizeof *entries); \
6737 size *= 2; \
6738 } \
6739 \
6740 entries[n].string = (STRING); \
6741 entries[n].overlay = (OVERLAY); \
6742 priority = Foverlay_get ((OVERLAY), Qpriority); \
6743 entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
6744 entries[n].after_string_p = (AFTER_P); \
6745 ++n; \
6746 } \
6747 while (false)
6748
6749
6750
6751 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6752 {
6753 Lisp_Object overlay = node->data;
6754 eassert (OVERLAYP (overlay));
6755 ptrdiff_t start = node->begin;
6756 ptrdiff_t end = node->end;
6757
6758
6759
6760 if (end != charpos && start != charpos)
6761 continue;
6762
6763
6764 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6765 if (WINDOWP (window) && XWINDOW (window) != it->w)
6766 continue;
6767
6768
6769
6770
6771 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6772 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6773
6774
6775 Lisp_Object str;
6776 if ((start == charpos || (end == charpos && invis != 0))
6777 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6778 && SCHARS (str))
6779 RECORD_OVERLAY_STRING (overlay, str, false);
6780
6781
6782 if ((end == charpos || (start == charpos && invis != 0))
6783 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6784 && SCHARS (str))
6785 RECORD_OVERLAY_STRING (overlay, str, true);
6786 }
6787
6788 #undef RECORD_OVERLAY_STRING
6789
6790
6791 if (n > 1)
6792 qsort (entries, n, sizeof *entries, compare_overlay_entries);
6793
6794
6795 it->n_overlay_strings = n;
6796 it->overlay_strings_charpos = charpos;
6797
6798
6799
6800
6801 ptrdiff_t j = it->current.overlay_string_index;
6802 for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++)
6803 {
6804 it->overlay_strings[i] = entries[j].string;
6805 it->string_overlays[i] = entries[j].overlay;
6806 }
6807
6808 CHECK_IT (it);
6809 SAFE_FREE ();
6810 }
6811
6812
6813
6814
6815
6816
6817 static bool
6818 get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, bool compute_stop_p)
6819 {
6820
6821
6822
6823
6824
6825
6826
6827 it->current.overlay_string_index = 0;
6828 load_overlay_strings (it, charpos);
6829
6830
6831
6832
6833 if (it->n_overlay_strings)
6834 {
6835
6836
6837
6838 if (compute_stop_p)
6839 compute_stop_pos (it);
6840 eassert (it->face_id >= 0);
6841
6842
6843
6844 eassert (!compute_stop_p || it->sp == 0);
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854 if (!(!it->bidi_p
6855 && STRINGP (it->string) && !SCHARS (it->string)))
6856 push_it (it, NULL);
6857
6858
6859
6860 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6861 it->string = it->overlay_strings[0];
6862 it->from_overlay = Qnil;
6863 it->stop_charpos = 0;
6864 eassert (STRINGP (it->string));
6865 it->end_charpos = SCHARS (it->string);
6866 it->prev_stop = 0;
6867 it->base_level_stop = 0;
6868 it->multibyte_p = STRING_MULTIBYTE (it->string);
6869 it->method = GET_FROM_STRING;
6870 it->from_disp_prop_p = 0;
6871 it->cmp_it.id = -1;
6872
6873
6874
6875 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6876 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6877 else
6878 it->paragraph_embedding = L2R;
6879
6880
6881 if (it->bidi_p)
6882 {
6883 ptrdiff_t pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
6884
6885 it->bidi_it.string.lstring = it->string;
6886 it->bidi_it.string.s = NULL;
6887 it->bidi_it.string.schars = SCHARS (it->string);
6888 it->bidi_it.string.bufpos = pos;
6889 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6890 it->bidi_it.string.unibyte = !it->multibyte_p;
6891 it->bidi_it.w = it->w;
6892 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6893 }
6894 return true;
6895 }
6896
6897 it->current.overlay_string_index = -1;
6898 return false;
6899 }
6900
6901 static bool
6902 get_overlay_strings (struct it *it, ptrdiff_t charpos)
6903 {
6904 it->string = Qnil;
6905 it->method = GET_FROM_BUFFER;
6906
6907 get_overlay_strings_1 (it, charpos, true);
6908
6909 CHECK_IT (it);
6910
6911
6912 return STRINGP (it->string);
6913 }
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927 static void
6928 push_it (struct it *it, struct text_pos *position)
6929 {
6930 struct iterator_stack_entry *p;
6931
6932 eassert (it->sp < IT_STACK_SIZE);
6933 p = it->stack + it->sp;
6934
6935 p->stop_charpos = it->stop_charpos;
6936 p->prev_stop = it->prev_stop;
6937 p->base_level_stop = it->base_level_stop;
6938 p->cmp_it = it->cmp_it;
6939 eassert (it->face_id >= 0);
6940 p->face_id = it->face_id;
6941 p->string = it->string;
6942 p->method = it->method;
6943 p->from_overlay = it->from_overlay;
6944 switch (p->method)
6945 {
6946 case GET_FROM_IMAGE:
6947 p->u.image.object = it->object;
6948 p->u.image.image_id = it->image_id;
6949 p->u.image.slice = it->slice;
6950 break;
6951 case GET_FROM_STRETCH:
6952 p->u.stretch.object = it->object;
6953 break;
6954 case GET_FROM_XWIDGET:
6955 p->u.xwidget.object = it->object;
6956 break;
6957 case GET_FROM_BUFFER:
6958 case GET_FROM_DISPLAY_VECTOR:
6959 case GET_FROM_STRING:
6960 case GET_FROM_C_STRING:
6961 break;
6962 default:
6963 emacs_abort ();
6964 }
6965 p->position = position ? *position : it->position;
6966 p->current = it->current;
6967 p->end_charpos = it->end_charpos;
6968 p->string_nchars = it->string_nchars;
6969 p->area = it->area;
6970 p->multibyte_p = it->multibyte_p;
6971 p->avoid_cursor_p = it->avoid_cursor_p;
6972 p->space_width = it->space_width;
6973 p->font_height = it->font_height;
6974 p->voffset = it->voffset;
6975 p->string_from_display_prop_p = it->string_from_display_prop_p;
6976 p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
6977 p->display_ellipsis_p = false;
6978 p->line_wrap = it->line_wrap;
6979 p->bidi_p = it->bidi_p;
6980 p->paragraph_embedding = it->paragraph_embedding;
6981 p->from_disp_prop_p = it->from_disp_prop_p;
6982 ++it->sp;
6983
6984
6985 if (it->bidi_p)
6986 bidi_push_it (&it->bidi_it);
6987 }
6988
6989 static void
6990 iterate_out_of_display_property (struct it *it)
6991 {
6992 bool buffer_p = !STRINGP (it->string);
6993 ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
6994 ptrdiff_t bob = (buffer_p ? BEGV : 0);
6995
6996 eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
6997
6998
6999
7000
7001 if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
7002 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
7003
7004 while (it->bidi_it.charpos >= bob
7005 && it->prev_stop <= it->bidi_it.charpos
7006 && it->bidi_it.charpos < CHARPOS (it->position)
7007 && it->bidi_it.charpos < eob)
7008 bidi_move_to_visually_next (&it->bidi_it);
7009
7010
7011 if (it->bidi_it.charpos > CHARPOS (it->position))
7012 it->prev_stop = CHARPOS (it->position);
7013
7014
7015 if (it->bidi_it.charpos != CHARPOS (it->position))
7016 SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
7017 if (buffer_p)
7018 it->current.pos = it->position;
7019 else
7020 it->current.string_pos = it->position;
7021 }
7022
7023
7024
7025
7026
7027 static void
7028 restore_face_box_flags (struct it *it, int prev_face_id)
7029 {
7030 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
7031
7032 if (face)
7033 {
7034 struct face *prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
7035
7036 if (!(it->start_of_box_run_p && prev_face && prev_face->box))
7037 it->start_of_box_run_p = (face->box != FACE_NO_BOX
7038 && (prev_face == NULL
7039 || prev_face->box == FACE_NO_BOX));
7040 it->face_box_p = face->box != FACE_NO_BOX;
7041 }
7042 }
7043
7044
7045
7046
7047
7048
7049
7050 static void
7051 pop_it (struct it *it)
7052 {
7053 struct iterator_stack_entry *p;
7054 bool from_display_prop = it->from_disp_prop_p;
7055 ptrdiff_t prev_pos = IT_CHARPOS (*it);
7056 int prev_face_id = it->face_id;
7057
7058 eassert (it->sp > 0);
7059 --it->sp;
7060 p = it->stack + it->sp;
7061 it->stop_charpos = p->stop_charpos;
7062 it->prev_stop = p->prev_stop;
7063 it->base_level_stop = p->base_level_stop;
7064 it->cmp_it = p->cmp_it;
7065 it->face_id = p->face_id;
7066 it->current = p->current;
7067 it->position = p->position;
7068 it->string = p->string;
7069 it->from_overlay = p->from_overlay;
7070 if (NILP (it->string))
7071 SET_TEXT_POS (it->current.string_pos, -1, -1);
7072 it->method = p->method;
7073 switch (it->method)
7074 {
7075 case GET_FROM_IMAGE:
7076 it->image_id = p->u.image.image_id;
7077 it->object = p->u.image.object;
7078 it->slice = p->u.image.slice;
7079 break;
7080 case GET_FROM_XWIDGET:
7081 it->object = p->u.xwidget.object;
7082 break;
7083 case GET_FROM_STRETCH:
7084 it->object = p->u.stretch.object;
7085 break;
7086 case GET_FROM_BUFFER:
7087 {
7088 restore_face_box_flags (it, prev_face_id);
7089 it->object = it->w->contents;
7090 }
7091 break;
7092 case GET_FROM_STRING:
7093 {
7094 restore_face_box_flags (it, prev_face_id);
7095 it->object = it->string;
7096 }
7097 break;
7098 case GET_FROM_DISPLAY_VECTOR:
7099 if (it->s)
7100 it->method = GET_FROM_C_STRING;
7101 else if (STRINGP (it->string))
7102 it->method = GET_FROM_STRING;
7103 else
7104 {
7105 it->method = GET_FROM_BUFFER;
7106 it->object = it->w->contents;
7107 }
7108 break;
7109 case GET_FROM_C_STRING:
7110 break;
7111 default:
7112 emacs_abort ();
7113 }
7114 it->end_charpos = p->end_charpos;
7115 it->string_nchars = p->string_nchars;
7116 it->area = p->area;
7117 it->multibyte_p = p->multibyte_p;
7118 it->avoid_cursor_p = p->avoid_cursor_p;
7119 it->space_width = p->space_width;
7120 it->font_height = p->font_height;
7121 it->voffset = p->voffset;
7122 it->string_from_display_prop_p = p->string_from_display_prop_p;
7123 it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
7124 it->line_wrap = p->line_wrap;
7125 it->bidi_p = p->bidi_p;
7126 it->paragraph_embedding = p->paragraph_embedding;
7127 it->from_disp_prop_p = p->from_disp_prop_p;
7128 if (it->bidi_p)
7129 {
7130 bidi_pop_it (&it->bidi_it);
7131
7132
7133
7134
7135
7136
7137
7138 if (from_display_prop
7139 && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
7140 iterate_out_of_display_property (it);
7141
7142 eassert ((BUFFERP (it->object)
7143 && IT_CHARPOS (*it) == it->bidi_it.charpos
7144 && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
7145 || (STRINGP (it->object)
7146 && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
7147 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
7148 || (CONSP (it->object) && it->method == GET_FROM_STRETCH)
7149
7150
7151
7152
7153
7154
7155 || it->sp > 0);
7156 }
7157
7158
7159
7160 if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
7161 it->ignore_overlay_strings_at_pos_p = false;
7162 }
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172 static void
7173 back_to_previous_line_start (struct it *it)
7174 {
7175 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
7176
7177 dec_both (&cp, &bp);
7178 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7179 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
7180 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
7181 }
7182
7183
7184
7185
7186
7187 static bool
7188 strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7189 {
7190 struct itree_node *node;
7191
7192 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7193 {
7194 Lisp_Object overlay = node->data;
7195 eassert (OVERLAYP (overlay));
7196
7197
7198 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7199 if (WINDOWP (window) && XWINDOW (window) != w)
7200 continue;
7201
7202 ptrdiff_t ostart = node->begin;
7203 ptrdiff_t oend = node->end;
7204
7205
7206 if (!((startpos < oend && ostart < endpos)
7207 || (ostart == oend
7208 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7209 continue;
7210
7211 Lisp_Object str;
7212 str = Foverlay_get (overlay, Qbefore_string);
7213 if (STRINGP (str) && SCHARS (str)
7214 && memchr (SDATA (str), '\n', SBYTES (str)))
7215 return true;
7216 str = Foverlay_get (overlay, Qafter_string);
7217 if (STRINGP (str) && SCHARS (str)
7218 && memchr (SDATA (str), '\n', SBYTES (str)))
7219 return true;
7220 }
7221
7222
7223 Lisp_Object cpos = make_fixnum (startpos);
7224 Lisp_Object limpos = make_fixnum (endpos);
7225
7226 while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos),
7227 !(NILP (cpos) || XFIXNAT (cpos) >= endpos)))
7228 {
7229 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
7230 Lisp_Object string = string_from_display_spec (spec);
7231 if (STRINGP (string)
7232 && memchr (SDATA (string), '\n', SBYTES (string)))
7233 return true;
7234 }
7235
7236 return false;
7237 }
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261 static bool
7262 forward_to_next_line_start (struct it *it, bool *skipped_p,
7263 struct bidi_it *bidi_it_prev)
7264 {
7265 ptrdiff_t old_selective;
7266 bool newline_found_p = false;
7267 int n;
7268 const int MAX_NEWLINE_DISTANCE = 500;
7269
7270
7271
7272 if (it->what == IT_CHARACTER
7273 && it->c == '\n'
7274 && CHARPOS (it->position) == IT_CHARPOS (*it))
7275 {
7276 if (it->bidi_p && bidi_it_prev)
7277 *bidi_it_prev = it->bidi_it;
7278 set_iterator_to_next (it, false);
7279 it->c = 0;
7280 return true;
7281 }
7282
7283
7284
7285
7286
7287 old_selective = it->selective;
7288 it->selective = 0;
7289
7290
7291
7292
7293 for (n = 0;
7294 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
7295 n += !STRINGP (it->string))
7296 {
7297 if (!get_next_display_element (it))
7298 return false;
7299 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
7300 if (newline_found_p && it->bidi_p && bidi_it_prev)
7301 *bidi_it_prev = it->bidi_it;
7302 set_iterator_to_next (it, false);
7303 }
7304
7305
7306
7307 if (!newline_found_p)
7308 {
7309 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
7310 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
7311 1, &bytepos);
7312 eassert (!STRINGP (it->string));
7313
7314
7315
7316
7317 bool no_strings_with_newlines = it->stop_charpos >= limit;
7318
7319 if (!no_strings_with_newlines)
7320 {
7321 if (!(current_buffer->long_line_optimizations_p
7322 && it->line_wrap == TRUNCATE))
7323 {
7324
7325
7326 Lisp_Object pos =
7327 Fnext_single_property_change (make_fixnum (start),
7328 Qdisplay, Qnil,
7329 make_fixnum (limit));
7330 no_strings_with_newlines =
7331 (NILP (pos) || XFIXNAT (pos) == limit)
7332 && next_overlay_change (start) == ZV;
7333 }
7334 else
7335 {
7336
7337
7338
7339
7340 no_strings_with_newlines =
7341 !strings_with_newlines (start, limit, it->w);
7342 }
7343 }
7344
7345
7346
7347
7348 if (no_strings_with_newlines)
7349 {
7350 if (!it->bidi_p || !bidi_it_prev)
7351 {
7352
7353 IT_CHARPOS (*it) = limit;
7354 IT_BYTEPOS (*it) = bytepos;
7355 }
7356 else
7357 {
7358
7359
7360
7361 struct bidi_it bprev;
7362
7363
7364
7365
7366 if (it->bidi_it.disp_pos < limit)
7367 {
7368 it->bidi_it.disp_pos = limit;
7369 it->bidi_it.disp_prop = 0;
7370 }
7371 do {
7372 bprev = it->bidi_it;
7373 bidi_move_to_visually_next (&it->bidi_it);
7374 } while (it->bidi_it.charpos != limit);
7375 IT_CHARPOS (*it) = limit;
7376 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7377 if (bidi_it_prev)
7378 *bidi_it_prev = bprev;
7379 }
7380 *skipped_p = newline_found_p = true;
7381 }
7382 else
7383 {
7384
7385 while (!newline_found_p)
7386 {
7387 if (!get_next_display_element (it))
7388 break;
7389 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
7390 if (newline_found_p && it->bidi_p && bidi_it_prev)
7391 *bidi_it_prev = it->bidi_it;
7392 set_iterator_to_next (it, false);
7393 }
7394 }
7395 }
7396
7397 it->selective = old_selective;
7398 return newline_found_p;
7399 }
7400
7401
7402
7403
7404
7405
7406
7407 static void
7408 back_to_previous_visible_line_start (struct it *it)
7409 {
7410 while (IT_CHARPOS (*it) > BEGV)
7411 {
7412 back_to_previous_line_start (it);
7413
7414 if (IT_CHARPOS (*it) <= BEGV)
7415 break;
7416
7417
7418
7419 if (it->selective > 0
7420 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7421 it->selective))
7422 continue;
7423
7424
7425 {
7426 Lisp_Object prop;
7427 prop = Fget_char_property (make_fixnum (IT_CHARPOS (*it) - 1),
7428 Qinvisible, it->window);
7429 if (TEXT_PROP_MEANS_INVISIBLE (prop) != 0)
7430 continue;
7431 }
7432
7433 if (IT_CHARPOS (*it) <= BEGV)
7434 break;
7435
7436 {
7437 struct it it2;
7438 void *it2data = NULL;
7439 ptrdiff_t pos;
7440 ptrdiff_t beg, end;
7441 Lisp_Object val, overlay;
7442
7443 SAVE_IT (it2, *it, it2data);
7444
7445
7446 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
7447 && beg < IT_CHARPOS (*it))
7448 goto replaced;
7449
7450
7451
7452 pos = --IT_CHARPOS (it2);
7453 --IT_BYTEPOS (it2);
7454 it2.sp = 0;
7455 bidi_unshelve_cache (NULL, false);
7456 it2.string_from_display_prop_p = false;
7457 it2.from_disp_prop_p = false;
7458 if (handle_display_prop (&it2) == HANDLED_RETURN
7459 && !NILP (val = get_char_property_and_overlay
7460 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7461 && (OVERLAYP (overlay)
7462 ? (beg = OVERLAY_START (overlay))
7463 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7464 {
7465 RESTORE_IT (it, it, it2data);
7466 goto replaced;
7467 }
7468
7469
7470 RESTORE_IT (it, it, it2data);
7471 break;
7472
7473 replaced:
7474 if (beg < BEGV)
7475 beg = BEGV;
7476 IT_CHARPOS (*it) = beg;
7477 IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
7478 }
7479 }
7480
7481 it->continuation_lines_width = 0;
7482
7483 eassert (IT_CHARPOS (*it) >= BEGV);
7484 eassert (it->medium_narrowing_begv > 0
7485 || IT_CHARPOS (*it) == BEGV
7486 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7487 CHECK_IT (it);
7488 }
7489
7490
7491
7492
7493
7494
7495
7496 void
7497 reseat_at_previous_visible_line_start (struct it *it)
7498 {
7499 back_to_previous_visible_line_start (it);
7500 reseat (it, it->current.pos, true);
7501 CHECK_IT (it);
7502 }
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512 static void
7513 reseat_at_next_visible_line_start (struct it *it, bool on_newline_p)
7514 {
7515 bool skipped_p = false;
7516 struct bidi_it bidi_it_prev;
7517 bool newline_found_p
7518 = forward_to_next_line_start (it, &skipped_p,
7519 on_newline_p ? &bidi_it_prev : NULL);
7520
7521
7522
7523 if (it->selective > 0)
7524 while (IT_CHARPOS (*it) < ZV
7525 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7526 it->selective))
7527 {
7528 eassert (IT_BYTEPOS (*it) == BEGV
7529 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7530 newline_found_p =
7531 forward_to_next_line_start (it, &skipped_p,
7532 on_newline_p ? &bidi_it_prev : NULL);
7533 }
7534
7535
7536 if (on_newline_p && newline_found_p)
7537 {
7538 if (STRINGP (it->string))
7539 {
7540 if (IT_STRING_CHARPOS (*it) > 0)
7541 {
7542 if (!it->bidi_p)
7543 {
7544 --IT_STRING_CHARPOS (*it);
7545 --IT_STRING_BYTEPOS (*it);
7546 }
7547 else
7548 {
7549
7550
7551
7552 it->bidi_it = bidi_it_prev;
7553 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
7554 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
7555 }
7556 }
7557 }
7558 else if (IT_CHARPOS (*it) > BEGV)
7559 {
7560 if (!it->bidi_p)
7561 {
7562 --IT_CHARPOS (*it);
7563 --IT_BYTEPOS (*it);
7564 }
7565 else
7566 {
7567
7568
7569 it->bidi_it = bidi_it_prev;
7570 IT_CHARPOS (*it) = it->bidi_it.charpos;
7571 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7572 }
7573 reseat (it, it->current.pos, false);
7574 }
7575 }
7576 else if (skipped_p)
7577 reseat (it, it->current.pos, false);
7578
7579 CHECK_IT (it);
7580 }
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593 static void
7594 reseat (struct it *it, struct text_pos pos, bool force_p)
7595 {
7596 ptrdiff_t original_pos = IT_CHARPOS (*it);
7597
7598 reseat_1 (it, pos, false);
7599
7600 if (current_buffer->long_line_optimizations_p)
7601 {
7602 if (!it->medium_narrowing_begv)
7603 {
7604 it->medium_narrowing_begv
7605 = get_medium_narrowing_begv (it->w, window_point (it->w));
7606 it->medium_narrowing_zv
7607 = get_medium_narrowing_zv (it->w, window_point (it->w));
7608 it->large_narrowing_begv
7609 = get_large_narrowing_begv (window_point (it->w));
7610 it->large_narrowing_zv
7611 = get_large_narrowing_zv (window_point (it->w));
7612 }
7613 else if ((pos.charpos < it->medium_narrowing_begv
7614 || pos.charpos > it->medium_narrowing_zv)
7615 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7616 {
7617 it->medium_narrowing_begv
7618 = get_medium_narrowing_begv (it->w, pos.charpos);
7619 it->medium_narrowing_zv
7620 = get_medium_narrowing_zv (it->w, pos.charpos);
7621 it->large_narrowing_begv
7622 = get_large_narrowing_begv (window_point (it->w));
7623 it->large_narrowing_zv
7624 = get_large_narrowing_zv (window_point (it->w));
7625 }
7626 }
7627
7628
7629
7630 if (force_p
7631 || CHARPOS (pos) > it->stop_charpos
7632 || CHARPOS (pos) < original_pos)
7633 {
7634 if (it->bidi_p)
7635 {
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646 if (CHARPOS (pos) != it->prev_stop)
7647 it->prev_stop = CHARPOS (pos);
7648 if (CHARPOS (pos) < it->base_level_stop)
7649 it->base_level_stop = 0;
7650 handle_stop (it);
7651 }
7652 else
7653 {
7654 handle_stop (it);
7655 it->prev_stop = it->base_level_stop = 0;
7656 }
7657
7658 }
7659
7660 CHECK_IT (it);
7661 }
7662
7663
7664
7665
7666
7667 static void
7668 reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7669 {
7670
7671 eassert (it->s == NULL);
7672
7673
7674 eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
7675
7676 it->current.pos = it->position = pos;
7677 it->end_charpos = ZV;
7678 it->dpvec = NULL;
7679 it->current.dpvec_index = -1;
7680 it->current.overlay_string_index = -1;
7681 IT_STRING_CHARPOS (*it) = -1;
7682 IT_STRING_BYTEPOS (*it) = -1;
7683 it->string = Qnil;
7684 it->method = GET_FROM_BUFFER;
7685 it->object = it->w->contents;
7686 it->area = TEXT_AREA;
7687 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
7688 it->sp = 0;
7689 it->string_from_display_prop_p = false;
7690 it->string_from_prefix_prop_p = false;
7691
7692 it->from_disp_prop_p = false;
7693 it->face_before_selective_p = false;
7694 if (it->bidi_p)
7695 {
7696 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7697 &it->bidi_it);
7698 bidi_unshelve_cache (NULL, false);
7699 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7700 it->bidi_it.string.s = NULL;
7701 it->bidi_it.string.lstring = Qnil;
7702 it->bidi_it.string.bufpos = 0;
7703 it->bidi_it.string.from_disp_str = false;
7704 it->bidi_it.string.unibyte = false;
7705 it->bidi_it.w = it->w;
7706 }
7707
7708 if (set_stop_p)
7709 {
7710 it->stop_charpos = CHARPOS (pos);
7711 it->base_level_stop = CHARPOS (pos);
7712 }
7713
7714 it->cmp_it.id = -1;
7715 it->min_width_property = Qnil;
7716 }
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737 static void
7738 reseat_to_string (struct it *it, const char *s, Lisp_Object string,
7739 ptrdiff_t charpos, ptrdiff_t precision, int field_width,
7740 int multibyte)
7741 {
7742
7743 it->stop_charpos = -1;
7744
7745
7746 memset (&it->current, 0, sizeof it->current);
7747 it->current.overlay_string_index = -1;
7748 it->current.dpvec_index = -1;
7749 eassert (charpos >= 0);
7750
7751
7752
7753 if (multibyte >= 0)
7754 it->multibyte_p = multibyte > 0;
7755
7756
7757
7758
7759
7760 it->bidi_p =
7761 !redisplay__inhibit_bidi
7762 && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
7763
7764 if (s == NULL)
7765 {
7766 eassert (STRINGP (string));
7767 it->string = string;
7768 it->s = NULL;
7769 it->end_charpos = it->string_nchars = SCHARS (string);
7770 it->method = GET_FROM_STRING;
7771 it->current.string_pos = string_pos (charpos, string);
7772
7773 if (it->bidi_p)
7774 {
7775 it->bidi_it.string.lstring = string;
7776 it->bidi_it.string.s = NULL;
7777 it->bidi_it.string.schars = it->end_charpos;
7778 it->bidi_it.string.bufpos = 0;
7779 it->bidi_it.string.from_disp_str = false;
7780 it->bidi_it.string.unibyte = !it->multibyte_p;
7781 it->bidi_it.w = it->w;
7782 bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
7783 FRAME_WINDOW_P (it->f), &it->bidi_it);
7784 }
7785 }
7786 else
7787 {
7788 it->s = (const unsigned char *) s;
7789 it->string = Qnil;
7790
7791
7792
7793 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
7794 if (it->multibyte_p)
7795 {
7796 it->current.pos = c_string_pos (charpos, s, true);
7797 it->end_charpos = it->string_nchars = number_of_chars (s, true);
7798 }
7799 else
7800 {
7801 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
7802 it->end_charpos = it->string_nchars = strlen (s);
7803 }
7804
7805 if (it->bidi_p)
7806 {
7807 it->bidi_it.string.lstring = Qnil;
7808 it->bidi_it.string.s = (const unsigned char *) s;
7809 it->bidi_it.string.schars = it->end_charpos;
7810 it->bidi_it.string.bufpos = 0;
7811 it->bidi_it.string.from_disp_str = false;
7812 it->bidi_it.string.unibyte = !it->multibyte_p;
7813 it->bidi_it.w = it->w;
7814 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7815 &it->bidi_it);
7816 }
7817 it->method = GET_FROM_C_STRING;
7818 }
7819
7820
7821
7822 if (precision > 0 && it->end_charpos - charpos > precision)
7823 {
7824 it->end_charpos = it->string_nchars = charpos + precision;
7825 if (it->bidi_p)
7826 it->bidi_it.string.schars = it->end_charpos;
7827 }
7828
7829
7830
7831
7832
7833 if (field_width < 0)
7834 field_width = DISP_INFINITY;
7835
7836
7837
7838 if (field_width > it->end_charpos - charpos)
7839 it->end_charpos = charpos + field_width;
7840
7841
7842 if (DISP_TABLE_P (Vstandard_display_table))
7843 it->dp = XCHAR_TABLE (Vstandard_display_table);
7844
7845 it->stop_charpos = charpos;
7846 it->prev_stop = charpos;
7847 it->base_level_stop = 0;
7848 if (it->bidi_p)
7849 {
7850 it->bidi_it.first_elt = true;
7851 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7852 it->bidi_it.disp_pos = -1;
7853 }
7854 if (s == NULL && it->multibyte_p)
7855 {
7856 ptrdiff_t endpos = SCHARS (it->string);
7857 if (endpos > it->end_charpos)
7858 endpos = it->end_charpos;
7859 composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
7860 it->string, true);
7861 }
7862 CHECK_IT (it);
7863 }
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873 typedef bool (*next_element_function) (struct it *);
7874
7875 static next_element_function const get_next_element[NUM_IT_METHODS] =
7876 {
7877 next_element_from_buffer,
7878 next_element_from_display_vector,
7879 next_element_from_string,
7880 next_element_from_c_string,
7881 next_element_from_image,
7882 next_element_from_stretch,
7883 next_element_from_xwidget,
7884 };
7885
7886 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897 #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS) \
7898 ((IT)->cmp_it.id >= 0 \
7899 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
7900 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
7901 END_CHARPOS, (IT)->w, \
7902 (IT)->bidi_p \
7903 ? (IT)->bidi_it.resolved_level \
7904 : -1, \
7905 FACE_FROM_ID_OR_NULL ((IT)->f, \
7906 (IT)->face_id), \
7907 (IT)->string)))
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917 Lisp_Object
7918 lookup_glyphless_char_display (int c, struct it *it)
7919 {
7920 Lisp_Object glyphless_method = Qnil;
7921
7922 if (CHAR_TABLE_P (Vglyphless_char_display)
7923 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
7924 {
7925 if (c >= 0)
7926 glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
7927 else
7928 glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
7929
7930 if (CONSP (glyphless_method))
7931 glyphless_method = FRAME_WINDOW_P (it->f)
7932 ? XCAR (glyphless_method)
7933 : XCDR (glyphless_method);
7934 }
7935
7936 retry:
7937 if (NILP (glyphless_method))
7938 {
7939 if (c >= 0)
7940
7941 return Qnil;
7942
7943 glyphless_method = Qempty_box;
7944 }
7945 if (EQ (glyphless_method, Qzero_width))
7946 {
7947 if (c >= 0)
7948 return glyphless_method;
7949
7950 glyphless_method = Qempty_box;
7951 }
7952 if (EQ (glyphless_method, Qthin_space))
7953 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
7954 else if (EQ (glyphless_method, Qempty_box))
7955 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
7956 else if (EQ (glyphless_method, Qhex_code))
7957 it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
7958 else if (STRINGP (glyphless_method))
7959 it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
7960 else
7961 {
7962
7963 glyphless_method = Qnil;
7964 goto retry;
7965 }
7966 it->what = IT_GLYPHLESS;
7967 return glyphless_method;
7968 }
7969
7970
7971
7972 static struct frame *last_escape_glyph_frame = NULL;
7973 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
7974 static int last_escape_glyph_merged_face_id = 0;
7975
7976 static int
7977 merge_escape_glyph_face (struct it *it)
7978 {
7979 int face_id;
7980
7981 if (it->f == last_escape_glyph_frame
7982 && it->face_id == last_escape_glyph_face_id)
7983 face_id = last_escape_glyph_merged_face_id;
7984 else
7985 {
7986
7987 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
7988 last_escape_glyph_frame = it->f;
7989 last_escape_glyph_face_id = it->face_id;
7990 last_escape_glyph_merged_face_id = face_id;
7991 }
7992 return face_id;
7993 }
7994
7995
7996
7997 static struct frame *last_glyphless_glyph_frame = NULL;
7998 static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
7999 static int last_glyphless_glyph_merged_face_id = 0;
8000
8001 int
8002 merge_glyphless_glyph_face (struct it *it)
8003 {
8004 int face_id;
8005
8006 if (it->f == last_glyphless_glyph_frame
8007 && it->face_id == last_glyphless_glyph_face_id)
8008 face_id = last_glyphless_glyph_merged_face_id;
8009 else
8010 {
8011
8012 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
8013 last_glyphless_glyph_frame = it->f;
8014 last_glyphless_glyph_face_id = it->face_id;
8015 last_glyphless_glyph_merged_face_id = face_id;
8016 }
8017 return face_id;
8018 }
8019
8020
8021
8022
8023 void
8024 forget_escape_and_glyphless_faces (void)
8025 {
8026 last_escape_glyph_frame = NULL;
8027 last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8028 last_glyphless_glyph_frame = NULL;
8029 last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8030 }
8031
8032
8033
8034
8035
8036 static bool
8037 get_next_display_element (struct it *it)
8038 {
8039
8040
8041
8042
8043 bool success_p;
8044
8045 get_next:
8046 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
8047
8048 if (it->what == IT_CHARACTER)
8049 {
8050
8051
8052
8053
8054
8055 if (it->bidi_p && it->bidi_it.type == STRONG_R
8056 && !inhibit_bidi_mirroring)
8057 it->c = bidi_mirror_char (it->c);
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067 if (success_p && it->dpvec == NULL)
8068 {
8069 Lisp_Object dv;
8070 struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
8071 bool nonascii_space_p = false;
8072 bool nonascii_hyphen_p = false;
8073 int c = it->c;
8074
8075 if (! it->multibyte_p && ! ASCII_CHAR_P (c))
8076 {
8077 eassert (SINGLE_BYTE_CHAR_P (c));
8078 if (unibyte_display_via_language_environment)
8079 {
8080 c = DECODE_CHAR (unibyte, c);
8081 if (c < 0)
8082 c = BYTE8_TO_CHAR (it->c);
8083 }
8084 else
8085 c = BYTE8_TO_CHAR (it->c);
8086 }
8087
8088 if (it->dp
8089 && (dv = DISP_CHAR_VECTOR (it->dp, c),
8090 VECTORP (dv)))
8091 {
8092 struct Lisp_Vector *v = XVECTOR (dv);
8093
8094
8095
8096
8097 if (v->header.size)
8098 {
8099 it->dpvec_char_len = it->len;
8100 it->dpvec = v->contents;
8101 it->dpend = v->contents + v->header.size;
8102 it->current.dpvec_index = 0;
8103 it->dpvec_face_id = -1;
8104 it->saved_face_id = it->face_id;
8105 it->method = GET_FROM_DISPLAY_VECTOR;
8106 it->ellipsis_p = false;
8107 }
8108 else
8109 {
8110 set_iterator_to_next (it, false);
8111 }
8112 goto get_next;
8113 }
8114
8115 if (! NILP (lookup_glyphless_char_display (c, it)))
8116 {
8117 if (it->what == IT_GLYPHLESS)
8118 goto done;
8119
8120 set_iterator_to_next (it, false);
8121 goto get_next;
8122 }
8123
8124
8125
8126 if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
8127 {
8128 if (blankp (c))
8129 nonascii_space_p = true;
8130 else if (c == SOFT_HYPHEN || c == HYPHEN
8131 || c == NON_BREAKING_HYPHEN)
8132 nonascii_hyphen_p = true;
8133 }
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146 if (((c < ' ' || c == 127)
8147 ? (it->area != TEXT_AREA
8148
8149 || (c != '\t'
8150 && it->glyph_row
8151 && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
8152 || (c != '\n' && c != '\t'))
8153 : (nonascii_space_p
8154 || nonascii_hyphen_p
8155 || CHAR_BYTE8_P (c)
8156 || ! CHAR_PRINTABLE_P (c))))
8157 {
8158
8159
8160
8161
8162
8163
8164 Lisp_Object gc;
8165 int ctl_len;
8166 int face_id;
8167 int lface_id = 0;
8168 int escape_glyph;
8169
8170
8171
8172 if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
8173 {
8174 int g;
8175
8176 g = '^';
8177
8178 if (it->dp
8179 && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8180 {
8181 g = GLYPH_CODE_CHAR (gc);
8182 lface_id = GLYPH_CODE_FACE (gc);
8183 }
8184
8185 face_id = (lface_id
8186 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8187 : merge_escape_glyph_face (it));
8188
8189 XSETINT (it->ctl_chars[0], g);
8190 XSETINT (it->ctl_chars[1], c ^ 0100);
8191 ctl_len = 2;
8192 goto display_control;
8193 }
8194
8195
8196
8197
8198 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
8199 {
8200
8201 face_id = merge_faces (it->w, Qnobreak_space, 0,
8202 it->face_id);
8203 XSETINT (it->ctl_chars[0],
8204 nobreak_char_ascii_display ? ' ' : it->c);
8205 ctl_len = 1;
8206 goto display_control;
8207 }
8208
8209
8210
8211
8212 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
8213 {
8214
8215 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
8216 it->face_id);
8217 XSETINT (it->ctl_chars[0],
8218 nobreak_char_ascii_display ? '-' : it->c);
8219 ctl_len = 1;
8220 goto display_control;
8221 }
8222
8223
8224
8225
8226 escape_glyph = '\\';
8227
8228 if (it->dp
8229 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8230 {
8231 escape_glyph = GLYPH_CODE_CHAR (gc);
8232 lface_id = GLYPH_CODE_FACE (gc);
8233 }
8234
8235 face_id = (lface_id
8236 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8237 : merge_escape_glyph_face (it));
8238
8239
8240
8241 if (nonascii_space_p || nonascii_hyphen_p)
8242 {
8243 XSETINT (it->ctl_chars[0], escape_glyph);
8244 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
8245 ctl_len = 2;
8246 goto display_control;
8247 }
8248
8249 {
8250 char str[10];
8251 int len, i;
8252
8253 if (CHAR_BYTE8_P (c))
8254
8255 c = CHAR_TO_BYTE8 (c);
8256 const char *format_string = display_raw_bytes_as_hex
8257 ? "x%02x"
8258 : "%03o";
8259 len = sprintf (str, format_string, c + 0u);
8260
8261 XSETINT (it->ctl_chars[0], escape_glyph);
8262 for (i = 0; i < len; i++)
8263 XSETINT (it->ctl_chars[i + 1], str[i]);
8264 ctl_len = len + 1;
8265 }
8266
8267 display_control:
8268
8269 it->dpvec_char_len = it->len;
8270 it->dpvec = it->ctl_chars;
8271 it->dpend = it->dpvec + ctl_len;
8272 it->current.dpvec_index = 0;
8273 it->dpvec_face_id = face_id;
8274 it->saved_face_id = it->face_id;
8275 it->method = GET_FROM_DISPLAY_VECTOR;
8276 it->ellipsis_p = false;
8277 goto get_next;
8278 }
8279 it->char_to_display = c;
8280 }
8281 else if (success_p)
8282 {
8283 it->char_to_display = it->c;
8284 }
8285 }
8286
8287 #ifdef HAVE_WINDOW_SYSTEM
8288
8289
8290 if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
8291 && it->multibyte_p
8292 && success_p
8293 && FRAME_WINDOW_P (it->f))
8294 {
8295 struct face *face = FACE_FROM_ID (it->f, it->face_id);
8296
8297 if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8298 {
8299
8300 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8301
8302 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8303 }
8304 else
8305 {
8306 ptrdiff_t pos = (it->s ? -1
8307 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8308 : IT_CHARPOS (*it));
8309 int c;
8310
8311 if (it->what == IT_CHARACTER)
8312 c = it->char_to_display;
8313 else
8314 {
8315 struct composition *cmp = composition_table[it->cmp_it.id];
8316 int i;
8317
8318 c = ' ';
8319 for (i = 0; i < cmp->glyph_len; i++)
8320
8321
8322 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8323 break;
8324 }
8325 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8326 }
8327 }
8328 #endif
8329
8330 done:
8331
8332
8333 if (it->face_box_p
8334 && it->s == NULL)
8335 {
8336 if (it->method == GET_FROM_STRING && it->sp)
8337 {
8338 int face_id = underlying_face_id (it);
8339 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8340
8341 if (face)
8342 {
8343 if (face->box == FACE_NO_BOX)
8344 {
8345
8346
8347 int string_face_id = face_after_it_pos (it);
8348 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8349 it->end_of_box_run_p = true;
8350 }
8351
8352
8353
8354 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8355
8356
8357
8358 || (it->what == IT_COMPOSITION
8359 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8360 >= SCHARS (it->string))))
8361
8362
8363 && ((it->current.overlay_string_index >= 0
8364 && (it->current.overlay_string_index
8365 == it->n_overlay_strings - 1))
8366
8367 || it->from_disp_prop_p))
8368 {
8369 ptrdiff_t ignore;
8370 int next_face_id;
8371 bool text_from_string = false;
8372
8373
8374 struct text_pos pos = it->current.pos;
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386 if (it->from_disp_prop_p)
8387 {
8388 int stackp = it->sp - 1;
8389
8390
8391 while (stackp >= 0
8392 && STRINGP ((it->stack + stackp)->string))
8393 stackp--;
8394 if (stackp < 0)
8395 {
8396
8397
8398
8399
8400
8401
8402 text_from_string = true;
8403 pos = it->stack[it->sp - 1].position;
8404 }
8405 else
8406 pos = (it->stack + stackp)->position;
8407 }
8408 else
8409 INC_TEXT_POS (pos, it->multibyte_p);
8410
8411 if (text_from_string)
8412 {
8413 Lisp_Object base_string = it->stack[it->sp - 1].string;
8414
8415 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8416 it->end_of_box_run_p = true;
8417 else
8418 {
8419 next_face_id
8420 = face_at_string_position (it->w, base_string,
8421 CHARPOS (pos), 0,
8422 &ignore, face_id,
8423 false, 0);
8424 if (FACE_FROM_ID (it->f, next_face_id)->box
8425 == FACE_NO_BOX)
8426 it->end_of_box_run_p = true;
8427 }
8428 }
8429 else if (CHARPOS (pos) >= ZV)
8430 it->end_of_box_run_p = true;
8431 else
8432 {
8433 next_face_id =
8434 face_at_buffer_position (it->w, CHARPOS (pos),
8435 &ignore,
8436 CHARPOS (pos)
8437 + TEXT_PROP_DISTANCE_LIMIT,
8438 false, -1, 0);
8439 if (FACE_FROM_ID (it->f, next_face_id)->box
8440 == FACE_NO_BOX)
8441 it->end_of_box_run_p = true;
8442 }
8443 }
8444 }
8445 }
8446
8447
8448 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8449 {
8450 int face_id = face_after_it_pos (it);
8451 if (face_id != it->face_id
8452 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8453 it->end_of_box_run_p = true;
8454 }
8455 }
8456
8457
8458
8459
8460
8461 if (!success_p && it->sp > 0)
8462 {
8463 set_iterator_to_next (it, false);
8464 success_p = get_next_display_element (it);
8465 }
8466
8467
8468 return success_p;
8469 }
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487 void
8488 set_iterator_to_next (struct it *it, bool reseat_p)
8489 {
8490
8491 if (max_redisplay_ticks > 0)
8492 update_redisplay_ticks (1, it->w);
8493
8494 switch (it->method)
8495 {
8496 case GET_FROM_BUFFER:
8497
8498
8499
8500 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8501 reseat_at_next_visible_line_start (it, false);
8502 else if (it->cmp_it.id >= 0)
8503 {
8504
8505 if (! it->bidi_p)
8506 {
8507 IT_CHARPOS (*it) += it->cmp_it.nchars;
8508 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8509 }
8510 else
8511 {
8512 int i;
8513
8514
8515
8516
8517 for (i = 0; i < it->cmp_it.nchars; i++)
8518 bidi_move_to_visually_next (&it->bidi_it);
8519 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8520 IT_CHARPOS (*it) = it->bidi_it.charpos;
8521 }
8522
8523 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8524 && it->cmp_it.to < it->cmp_it.nglyphs)
8525 {
8526
8527
8528 it->cmp_it.from = it->cmp_it.to;
8529 }
8530 else if ((it->bidi_p && it->cmp_it.reversed_p)
8531 && it->cmp_it.from > 0)
8532 {
8533
8534
8535 it->cmp_it.to = it->cmp_it.from;
8536 }
8537 else
8538 {
8539
8540
8541 ptrdiff_t stop = it->end_charpos;
8542
8543 if (it->bidi_it.scan_dir < 0)
8544
8545
8546 stop = -1;
8547 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8548 IT_BYTEPOS (*it), stop, Qnil, true);
8549 }
8550 }
8551 else
8552 {
8553 eassert (it->len != 0);
8554
8555 if (!it->bidi_p)
8556 {
8557 IT_BYTEPOS (*it) += it->len;
8558 IT_CHARPOS (*it) += 1;
8559 }
8560 else
8561 {
8562 int prev_scan_dir = it->bidi_it.scan_dir;
8563
8564
8565 if (it->bidi_it.new_paragraph)
8566 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8567 false);
8568 bidi_move_to_visually_next (&it->bidi_it);
8569 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8570 IT_CHARPOS (*it) = it->bidi_it.charpos;
8571 if (prev_scan_dir != it->bidi_it.scan_dir)
8572 {
8573
8574
8575 ptrdiff_t stop = it->end_charpos;
8576 if (it->bidi_it.scan_dir < 0)
8577 stop = -1;
8578 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8579 IT_BYTEPOS (*it), stop, Qnil,
8580 true);
8581 }
8582 }
8583 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8584 }
8585 break;
8586
8587 case GET_FROM_C_STRING:
8588
8589 if (!it->bidi_p
8590
8591
8592
8593
8594 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8595 {
8596 IT_BYTEPOS (*it) += it->len;
8597 IT_CHARPOS (*it) += 1;
8598 }
8599 else
8600 {
8601 bidi_move_to_visually_next (&it->bidi_it);
8602 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8603 IT_CHARPOS (*it) = it->bidi_it.charpos;
8604 }
8605 break;
8606
8607 case GET_FROM_DISPLAY_VECTOR:
8608
8609
8610
8611
8612 ++it->current.dpvec_index;
8613
8614
8615
8616 it->face_id = it->saved_face_id;
8617
8618 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8619 {
8620 bool recheck_faces = it->ellipsis_p;
8621
8622 if (it->s)
8623 it->method = GET_FROM_C_STRING;
8624 else if (STRINGP (it->string))
8625 it->method = GET_FROM_STRING;
8626 else
8627 {
8628 it->method = GET_FROM_BUFFER;
8629 it->object = it->w->contents;
8630 }
8631
8632 it->dpvec = NULL;
8633 it->current.dpvec_index = -1;
8634
8635
8636 if (it->dpvec_char_len < 0)
8637 reseat_at_next_visible_line_start (it, true);
8638 else if (it->dpvec_char_len > 0)
8639 {
8640 it->len = it->dpvec_char_len;
8641 set_iterator_to_next (it, reseat_p);
8642 }
8643
8644
8645 if (recheck_faces)
8646 {
8647 if (it->method == GET_FROM_STRING)
8648 it->stop_charpos = IT_STRING_CHARPOS (*it);
8649 else
8650 it->stop_charpos = IT_CHARPOS (*it);
8651 }
8652 }
8653 break;
8654
8655 case GET_FROM_STRING:
8656
8657 eassert (it->s == NULL && STRINGP (it->string));
8658
8659
8660
8661
8662
8663 if (it->current.overlay_string_index >= 0)
8664 {
8665
8666
8667
8668 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8669 goto consider_string_end;
8670 }
8671 else
8672 {
8673
8674
8675 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8676 goto consider_string_end;
8677 }
8678 if (it->cmp_it.id >= 0)
8679 {
8680
8681
8682
8683 if (! it->bidi_p)
8684 {
8685 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8686 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8687 }
8688 else
8689 {
8690 int i;
8691
8692 for (i = 0; i < it->cmp_it.nchars; i++)
8693 bidi_move_to_visually_next (&it->bidi_it);
8694 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8695 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8696 }
8697
8698
8699
8700 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8701 && (it->cmp_it.to < it->cmp_it.nglyphs))
8702 {
8703
8704
8705 it->cmp_it.from = it->cmp_it.to;
8706 }
8707 else if ((it->bidi_p && it->cmp_it.reversed_p)
8708 && it->cmp_it.from > 0)
8709 {
8710
8711
8712 it->cmp_it.to = it->cmp_it.from;
8713 }
8714 else
8715 {
8716
8717
8718
8719
8720
8721
8722 ptrdiff_t stop = SCHARS (it->string);
8723
8724 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8725 stop = -1;
8726 else if (it->end_charpos < stop)
8727 {
8728
8729
8730
8731 stop = it->end_charpos;
8732 }
8733 composition_compute_stop_pos (&it->cmp_it,
8734 IT_STRING_CHARPOS (*it),
8735 IT_STRING_BYTEPOS (*it), stop,
8736 it->string, true);
8737 }
8738 }
8739 else
8740 {
8741 if (!it->bidi_p
8742
8743
8744
8745
8746
8747 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8748 {
8749 IT_STRING_BYTEPOS (*it) += it->len;
8750 IT_STRING_CHARPOS (*it) += 1;
8751 }
8752 else
8753 {
8754 int prev_scan_dir = it->bidi_it.scan_dir;
8755
8756 bidi_move_to_visually_next (&it->bidi_it);
8757 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8758 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8759
8760
8761 if (prev_scan_dir != it->bidi_it.scan_dir)
8762 {
8763 ptrdiff_t stop = SCHARS (it->string);
8764
8765 if (it->bidi_it.scan_dir < 0)
8766 stop = -1;
8767 else if (it->end_charpos < stop)
8768 stop = it->end_charpos;
8769
8770 composition_compute_stop_pos (&it->cmp_it,
8771 IT_STRING_CHARPOS (*it),
8772 IT_STRING_BYTEPOS (*it), stop,
8773 it->string, true);
8774 }
8775 }
8776 }
8777
8778 consider_string_end:
8779
8780 if (it->current.overlay_string_index >= 0)
8781 {
8782
8783
8784 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8785 {
8786 it->ellipsis_p = false;
8787 next_overlay_string (it);
8788 if (it->ellipsis_p)
8789 setup_for_ellipsis (it, 0);
8790 }
8791 }
8792 else
8793 {
8794
8795
8796
8797
8798 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8799 && it->sp > 0)
8800 {
8801 pop_it (it);
8802 if (it->method == GET_FROM_STRING)
8803 goto consider_string_end;
8804 }
8805 }
8806 break;
8807
8808 case GET_FROM_IMAGE:
8809 case GET_FROM_STRETCH:
8810 case GET_FROM_XWIDGET:
8811
8812
8813
8814
8815 eassert (it->sp > 0);
8816 pop_it (it);
8817 if (it->method == GET_FROM_STRING)
8818 goto consider_string_end;
8819 break;
8820
8821 default:
8822
8823 emacs_abort ();
8824 }
8825
8826 eassert (it->method != GET_FROM_STRING
8827 || (STRINGP (it->string)
8828 && IT_STRING_CHARPOS (*it) >= 0));
8829 }
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840 static bool
8841 next_element_from_display_vector (struct it *it)
8842 {
8843 Lisp_Object gc;
8844 int prev_face_id = it->face_id;
8845 int next_face_id;
8846
8847
8848 eassert (it->dpvec && it->current.dpvec_index >= 0);
8849
8850 it->face_id = it->saved_face_id;
8851
8852
8853
8854 if (it->dpend - it->dpvec > 0
8855 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8856 {
8857 struct face *this_face, *prev_face, *next_face;
8858
8859 it->c = GLYPH_CODE_CHAR (gc);
8860 it->len = CHAR_BYTES (it->c);
8861
8862
8863
8864
8865 if (it->dpvec_face_id >= 0)
8866 it->face_id = it->dpvec_face_id;
8867 else
8868 {
8869 int lface_id = GLYPH_CODE_FACE (gc);
8870 if (lface_id > 0)
8871 it->face_id = merge_faces (it->w, Qt, lface_id,
8872 it->saved_face_id);
8873 }
8874
8875
8876
8877
8878 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8879 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8880
8881
8882 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8883 && (!prev_face
8884 || prev_face->box == FACE_NO_BOX));
8885
8886
8887
8888
8889 next_face_id = it->saved_face_id;
8890 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8891 {
8892 if (it->dpvec_face_id >= 0)
8893 next_face_id = it->dpvec_face_id;
8894 else
8895 {
8896 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8897 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8898
8899 if (lface_id > 0)
8900 next_face_id = merge_faces (it->w, Qt, lface_id,
8901 it->saved_face_id);
8902 }
8903 }
8904 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8905 if (this_face && this_face->box != FACE_NO_BOX
8906 && (!next_face || next_face->box == FACE_NO_BOX))
8907 it->end_of_box_run_p = true;
8908 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8909 }
8910 else
8911
8912 it->c = ' ', it->len = 1;
8913
8914
8915
8916
8917 it->what = IT_CHARACTER;
8918 return true;
8919 }
8920
8921
8922
8923 static void
8924 get_visually_first_element (struct it *it)
8925 {
8926 bool string_p = STRINGP (it->string) || it->s;
8927 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8928 ptrdiff_t bob;
8929 ptrdiff_t obegv = BEGV;
8930
8931 SET_WITH_NARROWED_BEGV (it, bob,
8932 string_p ? 0 :
8933 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8934 it->medium_narrowing_begv);
8935
8936 if (STRINGP (it->string))
8937 {
8938 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8939 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8940 }
8941 else
8942 {
8943 it->bidi_it.charpos = IT_CHARPOS (*it);
8944 it->bidi_it.bytepos = IT_BYTEPOS (*it);
8945 }
8946
8947 if (it->bidi_it.charpos == eob)
8948 {
8949
8950
8951
8952 it->bidi_it.first_elt = false;
8953 }
8954 else if (it->bidi_it.charpos == bob
8955 || (!string_p
8956 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
8957 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
8958 {
8959
8960
8961 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8962 bidi_move_to_visually_next (&it->bidi_it);
8963 }
8964 else
8965 {
8966 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
8967
8968
8969
8970
8971 if (string_p)
8972 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
8973 else
8974 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
8975 find_newline_no_quit (IT_CHARPOS (*it),
8976 IT_BYTEPOS (*it), -1,
8977 &it->bidi_it.bytepos),
8978 it->medium_narrowing_begv);
8979 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8980 do
8981 {
8982
8983
8984 bidi_move_to_visually_next (&it->bidi_it);
8985 }
8986 while (it->bidi_it.bytepos != orig_bytepos
8987 && it->bidi_it.charpos < eob);
8988 }
8989
8990
8991 if (STRINGP (it->string))
8992 {
8993 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8994 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8995 }
8996 else
8997 {
8998 IT_CHARPOS (*it) = it->bidi_it.charpos;
8999 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
9000 }
9001
9002 if (STRINGP (it->string) || !it->s)
9003 {
9004 ptrdiff_t stop, charpos, bytepos;
9005
9006 if (STRINGP (it->string))
9007 {
9008 eassert (!it->s);
9009 stop = SCHARS (it->string);
9010 if (stop > it->end_charpos)
9011 stop = it->end_charpos;
9012 charpos = IT_STRING_CHARPOS (*it);
9013 bytepos = IT_STRING_BYTEPOS (*it);
9014 }
9015 else
9016 {
9017 stop = it->end_charpos;
9018 charpos = IT_CHARPOS (*it);
9019 bytepos = IT_BYTEPOS (*it);
9020 }
9021 if (it->bidi_it.scan_dir < 0)
9022 stop = -1;
9023 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9024 it->string, true);
9025 }
9026 }
9027
9028
9029
9030
9031
9032
9033 static bool
9034 next_element_from_string (struct it *it)
9035 {
9036 struct text_pos position;
9037
9038 eassert (STRINGP (it->string));
9039 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9040 eassert (IT_STRING_CHARPOS (*it) >= 0);
9041 position = it->current.string_pos;
9042
9043
9044
9045
9046
9047 if (it->bidi_p && it->bidi_it.first_elt)
9048 {
9049 get_visually_first_element (it);
9050 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9051 }
9052
9053
9054 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9055 {
9056 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9057 {
9058 if (!(!it->bidi_p
9059 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9060 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9061 {
9062
9063
9064
9065
9066
9067
9068 handle_stop_backwards (it, it->stop_charpos);
9069 return GET_NEXT_DISPLAY_ELEMENT (it);
9070 }
9071 else
9072 {
9073 if (it->bidi_p)
9074 {
9075
9076
9077 it->prev_stop = it->stop_charpos;
9078
9079
9080
9081 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9082 it->base_level_stop = it->stop_charpos;
9083 }
9084 handle_stop (it);
9085
9086
9087
9088 return GET_NEXT_DISPLAY_ELEMENT (it);
9089 }
9090 }
9091 else if (it->bidi_p
9092
9093
9094
9095 && IT_STRING_CHARPOS (*it) < it->prev_stop
9096
9097
9098
9099
9100 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9101 {
9102
9103
9104
9105
9106 if (it->base_level_stop <= 0
9107 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9108 it->base_level_stop = 0;
9109 handle_stop_backwards (it, it->base_level_stop);
9110 return GET_NEXT_DISPLAY_ELEMENT (it);
9111 }
9112 }
9113
9114 if (it->current.overlay_string_index >= 0)
9115 {
9116
9117
9118
9119 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9120 {
9121 it->what = IT_EOB;
9122 return false;
9123 }
9124 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9125 IT_STRING_BYTEPOS (*it),
9126 it->bidi_it.scan_dir < 0
9127 ? -1
9128 : SCHARS (it->string))
9129 && next_element_from_composition (it))
9130 {
9131 return true;
9132 }
9133 else if (STRING_MULTIBYTE (it->string))
9134 {
9135 const unsigned char *s = (SDATA (it->string)
9136 + IT_STRING_BYTEPOS (*it));
9137 it->c = check_char_and_length (s, &it->len);
9138 }
9139 else
9140 {
9141 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9142 it->len = 1;
9143 }
9144 }
9145 else
9146 {
9147
9148
9149
9150
9151 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9152 {
9153 it->what = IT_EOB;
9154 return false;
9155 }
9156 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9157 {
9158
9159 it->c = ' ', it->len = 1;
9160 CHARPOS (position) = BYTEPOS (position) = -1;
9161 }
9162 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9163 IT_STRING_BYTEPOS (*it),
9164 it->bidi_it.scan_dir < 0
9165 ? -1
9166 : it->string_nchars)
9167 && next_element_from_composition (it))
9168 {
9169 return true;
9170 }
9171 else if (STRING_MULTIBYTE (it->string))
9172 {
9173 const unsigned char *s = (SDATA (it->string)
9174 + IT_STRING_BYTEPOS (*it));
9175 it->c = check_char_and_length (s, &it->len);
9176 }
9177 else
9178 {
9179 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9180 it->len = 1;
9181 }
9182 }
9183
9184
9185 it->what = IT_CHARACTER;
9186 it->object = it->string;
9187 it->position = position;
9188 return true;
9189 }
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199 static bool
9200 next_element_from_c_string (struct it *it)
9201 {
9202 bool success_p = true;
9203
9204 eassert (it->s);
9205 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9206 it->what = IT_CHARACTER;
9207 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9208 it->object = make_fixnum (0);
9209
9210
9211
9212
9213
9214 if (it->bidi_p && it->bidi_it.first_elt)
9215 get_visually_first_element (it);
9216
9217
9218
9219
9220 if (IT_CHARPOS (*it) >= it->end_charpos)
9221 {
9222
9223 it->what = IT_EOB;
9224 success_p = false;
9225 }
9226 else if (IT_CHARPOS (*it) >= it->string_nchars)
9227 {
9228
9229 it->c = ' ', it->len = 1;
9230 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9231 }
9232 else if (it->multibyte_p)
9233 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9234 else
9235 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9236
9237 return success_p;
9238 }
9239
9240
9241
9242
9243
9244
9245
9246 static bool
9247 next_element_from_ellipsis (struct it *it)
9248 {
9249 if (it->selective_display_ellipsis_p)
9250 setup_for_ellipsis (it, it->len);
9251 else
9252 {
9253
9254
9255
9256
9257 it->saved_face_id = it->face_id;
9258 it->method = GET_FROM_BUFFER;
9259 it->object = it->w->contents;
9260 reseat_at_next_visible_line_start (it, true);
9261 it->face_before_selective_p = true;
9262 }
9263
9264 return GET_NEXT_DISPLAY_ELEMENT (it);
9265 }
9266
9267
9268
9269
9270
9271
9272
9273 static bool
9274 next_element_from_image (struct it *it)
9275 {
9276 it->what = IT_IMAGE;
9277 return true;
9278 }
9279
9280 static bool
9281 next_element_from_xwidget (struct it *it)
9282 {
9283 it->what = IT_XWIDGET;
9284 return true;
9285 }
9286
9287
9288
9289
9290
9291
9292 static bool
9293 next_element_from_stretch (struct it *it)
9294 {
9295 it->what = IT_STRETCH;
9296 return true;
9297 }
9298
9299
9300
9301
9302
9303
9304 static void
9305 compute_stop_pos_backwards (struct it *it)
9306 {
9307 const int SCAN_BACK_LIMIT = 1000;
9308 struct text_pos pos;
9309 struct display_pos save_current = it->current;
9310 struct text_pos save_position = it->position;
9311 ptrdiff_t charpos = IT_CHARPOS (*it);
9312 ptrdiff_t where_we_are = charpos;
9313 ptrdiff_t save_stop_pos = it->stop_charpos;
9314 ptrdiff_t save_end_pos = it->end_charpos;
9315
9316 eassert (NILP (it->string) && !it->s);
9317 eassert (it->bidi_p);
9318 it->bidi_p = false;
9319 do
9320 {
9321 it->end_charpos = min (charpos + 1, ZV);
9322 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9323 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9324 reseat_1 (it, pos, false);
9325 compute_stop_pos (it);
9326
9327 if (it->stop_charpos <= charpos)
9328 emacs_abort ();
9329 }
9330 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9331
9332 if (it->stop_charpos <= where_we_are)
9333 it->prev_stop = it->stop_charpos;
9334 else
9335 it->prev_stop = BEGV;
9336 it->bidi_p = true;
9337 it->current = save_current;
9338 it->position = save_position;
9339 it->stop_charpos = save_stop_pos;
9340 it->end_charpos = save_end_pos;
9341 }
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351 static void
9352 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9353 {
9354 bool bufp = !STRINGP (it->string);
9355 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9356 struct display_pos save_current = it->current;
9357 struct text_pos save_position = it->position;
9358 struct composition_it save_cmp_it = it->cmp_it;
9359 struct text_pos pos1;
9360 ptrdiff_t next_stop;
9361
9362
9363 eassert (it->bidi_p);
9364 it->bidi_p = false;
9365 do
9366 {
9367 it->prev_stop = charpos;
9368 if (bufp)
9369 {
9370 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9371 reseat_1 (it, pos1, false);
9372 }
9373 else
9374 it->current.string_pos = string_pos (charpos, it->string);
9375 compute_stop_pos (it);
9376
9377 if (it->stop_charpos <= it->prev_stop)
9378 emacs_abort ();
9379 charpos = it->stop_charpos;
9380 }
9381 while (charpos <= where_we_are);
9382
9383 it->bidi_p = true;
9384 it->current = save_current;
9385 it->position = save_position;
9386 it->cmp_it = save_cmp_it;
9387 next_stop = it->stop_charpos;
9388 it->stop_charpos = it->prev_stop;
9389 handle_stop (it);
9390 it->stop_charpos = next_stop;
9391 }
9392
9393
9394
9395
9396
9397
9398 static bool
9399 next_element_from_buffer (struct it *it)
9400 {
9401 bool success_p = true;
9402
9403 eassert (IT_CHARPOS (*it) >= BEGV);
9404 eassert (NILP (it->string) && !it->s);
9405 eassert (!it->bidi_p
9406 || (NILP (it->bidi_it.string.lstring)
9407 && it->bidi_it.string.s == NULL));
9408
9409
9410
9411
9412
9413 if (it->bidi_p && it->bidi_it.first_elt)
9414 {
9415 get_visually_first_element (it);
9416 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9417 }
9418
9419 if (IT_CHARPOS (*it) >= it->stop_charpos)
9420 {
9421 if (IT_CHARPOS (*it) >= it->end_charpos)
9422 {
9423 bool overlay_strings_follow_p;
9424
9425
9426
9427 if (it->overlay_strings_at_end_processed_p)
9428 overlay_strings_follow_p = false;
9429 else
9430 {
9431 it->overlay_strings_at_end_processed_p = true;
9432 overlay_strings_follow_p = get_overlay_strings (it, 0);
9433 }
9434
9435 if (overlay_strings_follow_p)
9436 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9437 else
9438 {
9439 it->what = IT_EOB;
9440 it->position = it->current.pos;
9441 success_p = false;
9442 }
9443 }
9444 else if (!(!it->bidi_p
9445 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9446 || IT_CHARPOS (*it) == it->stop_charpos))
9447 {
9448
9449
9450
9451
9452
9453
9454 handle_stop_backwards (it, it->stop_charpos);
9455 it->ignore_overlay_strings_at_pos_p = false;
9456 return GET_NEXT_DISPLAY_ELEMENT (it);
9457 }
9458 else
9459 {
9460 if (it->bidi_p)
9461 {
9462
9463
9464 it->prev_stop = it->stop_charpos;
9465
9466
9467
9468 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9469 it->base_level_stop = it->stop_charpos;
9470 }
9471 handle_stop (it);
9472 it->ignore_overlay_strings_at_pos_p = false;
9473 return GET_NEXT_DISPLAY_ELEMENT (it);
9474 }
9475 }
9476 else if (it->bidi_p
9477
9478
9479
9480 && IT_CHARPOS (*it) < it->prev_stop
9481
9482
9483
9484
9485 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9486 {
9487 if (it->base_level_stop <= 0
9488 || IT_CHARPOS (*it) < it->base_level_stop)
9489 {
9490
9491
9492
9493
9494 it->base_level_stop = BEGV;
9495 compute_stop_pos_backwards (it);
9496 handle_stop_backwards (it, it->prev_stop);
9497 }
9498 else
9499 handle_stop_backwards (it, it->base_level_stop);
9500 it->ignore_overlay_strings_at_pos_p = false;
9501 return GET_NEXT_DISPLAY_ELEMENT (it);
9502 }
9503 else
9504 {
9505
9506
9507 unsigned char *p;
9508 ptrdiff_t stop;
9509
9510
9511
9512 it->ignore_overlay_strings_at_pos_p = false;
9513
9514 if (composition_break_at_point
9515 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9516 && !NILP (Vauto_composition_mode))
9517 {
9518
9519 if (it->bidi_it.scan_dir < 0)
9520 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9521 else
9522 stop = (IT_CHARPOS (*it) < PT
9523 && PT < it->end_charpos) ? PT : it->end_charpos;
9524 }
9525 else
9526 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9527 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9528 stop)
9529 && next_element_from_composition (it))
9530 {
9531 return true;
9532 }
9533
9534
9535 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9536 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9537 it->c = string_char_and_length (p, &it->len);
9538 else
9539 it->c = *p, it->len = 1;
9540
9541
9542 it->what = IT_CHARACTER;
9543 it->object = it->w->contents;
9544 it->position = it->current.pos;
9545
9546
9547
9548 if (it->selective)
9549 {
9550 if (it->c == '\n')
9551 {
9552
9553
9554 if (it->selective > 0
9555 && IT_CHARPOS (*it) + 1 < ZV
9556 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9557 IT_BYTEPOS (*it) + 1,
9558 it->selective))
9559 {
9560 success_p = next_element_from_ellipsis (it);
9561 it->dpvec_char_len = -1;
9562 }
9563 }
9564 else if (it->c == '\r' && it->selective == -1)
9565 {
9566
9567
9568
9569 success_p = next_element_from_ellipsis (it);
9570 it->dpvec_char_len = -1;
9571 }
9572 }
9573 }
9574
9575
9576 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9577 return success_p;
9578 }
9579
9580
9581
9582
9583
9584
9585
9586 static bool
9587 next_element_from_composition (struct it *it)
9588 {
9589 it->what = IT_COMPOSITION;
9590 it->len = it->cmp_it.nbytes;
9591 if (STRINGP (it->string))
9592 {
9593 if (it->c < 0)
9594 {
9595 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9596 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9597 return false;
9598 }
9599 it->position = it->current.string_pos;
9600 it->object = it->string;
9601 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9602 IT_STRING_BYTEPOS (*it), it->string);
9603 }
9604 else
9605 {
9606 if (it->c < 0)
9607 {
9608 IT_CHARPOS (*it) += it->cmp_it.nchars;
9609 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9610 if (it->bidi_p)
9611 {
9612 if (it->bidi_it.new_paragraph)
9613 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9614 false);
9615
9616
9617 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9618 bidi_move_to_visually_next (&it->bidi_it);
9619 }
9620 return false;
9621 }
9622 it->position = it->current.pos;
9623 it->object = it->w->contents;
9624 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9625 IT_BYTEPOS (*it), Qnil);
9626 }
9627 return true;
9628 }
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9640 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676 static enum move_it_result
9677 move_it_in_display_line_to (struct it *it,
9678 ptrdiff_t to_charpos, int to_x,
9679 enum move_operation_enum op)
9680 {
9681 enum move_it_result result = MOVE_UNDEFINED;
9682 struct glyph_row *saved_glyph_row;
9683 struct it wrap_it, atpos_it, atx_it, ppos_it;
9684 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9685 void *ppos_data = NULL;
9686 bool may_wrap = false;
9687 enum it_method prev_method = it->method;
9688 ptrdiff_t closest_pos UNINIT;
9689 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9690 bool saw_smaller_pos = prev_pos < to_charpos;
9691 bool line_number_pending = false;
9692
9693
9694 saved_glyph_row = it->glyph_row;
9695 it->glyph_row = NULL;
9696
9697
9698
9699
9700
9701
9702 wrap_it.sp = -1;
9703 atpos_it.sp = -1;
9704 atx_it.sp = -1;
9705
9706
9707
9708
9709
9710
9711
9712
9713 if (it->bidi_p)
9714 {
9715 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9716 {
9717 SAVE_IT (ppos_it, *it, ppos_data);
9718 closest_pos = IT_CHARPOS (*it);
9719 }
9720 else
9721 closest_pos = ZV;
9722 }
9723
9724 #define BUFFER_POS_REACHED_P() \
9725 ((op & MOVE_TO_POS) != 0 \
9726 && BUFFERP (it->object) \
9727 && (IT_CHARPOS (*it) == to_charpos \
9728 || ((!it->bidi_p \
9729 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9730 && IT_CHARPOS (*it) > to_charpos) \
9731 || (it->what == IT_COMPOSITION \
9732 && ((IT_CHARPOS (*it) > to_charpos \
9733 && to_charpos >= it->cmp_it.charpos) \
9734 || (IT_CHARPOS (*it) < to_charpos \
9735 && to_charpos <= it->cmp_it.charpos)))) \
9736 && (it->method == GET_FROM_BUFFER \
9737 || (it->method == GET_FROM_DISPLAY_VECTOR \
9738 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9739
9740 if (it->hpos == 0)
9741 {
9742
9743
9744
9745
9746 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9747 && should_produce_line_number (it))
9748 {
9749 if (it->current_x == it->first_visible_x)
9750 maybe_produce_line_number (it);
9751 else
9752 line_number_pending = true;
9753 }
9754
9755 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9756 handle_line_prefix (it);
9757 }
9758
9759 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9760 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9761
9762 while (true)
9763 {
9764 int x, i, ascent = 0, descent = 0;
9765
9766
9767 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9768 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9769 (IT)->max_descent = descent)
9770
9771
9772
9773 if ((op & MOVE_TO_POS) != 0
9774 && BUFFERP (it->object)
9775 && it->method == GET_FROM_BUFFER
9776 && (((!it->bidi_p
9777
9778
9779
9780
9781 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9782 && IT_CHARPOS (*it) > to_charpos)
9783 || (it->bidi_p
9784 && (prev_method == GET_FROM_IMAGE
9785 || prev_method == GET_FROM_STRETCH
9786 || prev_method == GET_FROM_STRING)
9787
9788 && ((prev_pos < to_charpos
9789 && IT_CHARPOS (*it) >= to_charpos)
9790
9791 || (prev_pos > to_charpos
9792 && IT_CHARPOS (*it) <= to_charpos)))))
9793 {
9794 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9795 {
9796 result = MOVE_POS_MATCH_OR_ZV;
9797 break;
9798 }
9799 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9800
9801
9802
9803 SAVE_IT (atpos_it, *it, atpos_data);
9804 }
9805
9806
9807
9808
9809
9810 if (!get_next_display_element (it))
9811 {
9812 result = MOVE_POS_MATCH_OR_ZV;
9813 break;
9814 }
9815
9816 if (it->line_wrap == TRUNCATE)
9817 {
9818
9819
9820
9821
9822
9823
9824 if (BUFFER_POS_REACHED_P ()
9825 && (it->pixel_width > 0
9826 || IT_CHARPOS (*it) > to_charpos
9827 || it->area != TEXT_AREA))
9828 {
9829 result = MOVE_POS_MATCH_OR_ZV;
9830 break;
9831 }
9832 }
9833 else
9834 {
9835 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9836 {
9837 bool next_may_wrap = may_wrap;
9838
9839 if (char_can_wrap_after (it))
9840 next_may_wrap = true;
9841 else
9842 next_may_wrap = false;
9843
9844 if (may_wrap && char_can_wrap_before (it))
9845 {
9846
9847
9848
9849
9850
9851 if (atpos_it.sp >= 0)
9852 {
9853 RESTORE_IT (it, &atpos_it, atpos_data);
9854 result = MOVE_POS_MATCH_OR_ZV;
9855 goto done;
9856 }
9857 if (atx_it.sp >= 0)
9858 {
9859 RESTORE_IT (it, &atx_it, atx_data);
9860 result = MOVE_X_REACHED;
9861 goto done;
9862 }
9863
9864 SAVE_IT (wrap_it, *it, wrap_data);
9865 }
9866
9867 may_wrap = next_may_wrap;
9868 }
9869 }
9870
9871
9872
9873 ascent = it->max_ascent;
9874 descent = it->max_descent;
9875
9876
9877
9878
9879
9880 x = it->current_x;
9881
9882 PRODUCE_GLYPHS (it);
9883
9884 if (it->area != TEXT_AREA)
9885 {
9886 prev_method = it->method;
9887 if (it->method == GET_FROM_BUFFER)
9888 prev_pos = IT_CHARPOS (*it);
9889 set_iterator_to_next (it, true);
9890 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9891 SET_TEXT_POS (this_line_min_pos,
9892 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9893 if (it->bidi_p
9894 && (op & MOVE_TO_POS)
9895 && IT_CHARPOS (*it) > to_charpos
9896 && IT_CHARPOS (*it) < closest_pos)
9897 closest_pos = IT_CHARPOS (*it);
9898 continue;
9899 }
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916
9917
9918
9919 if (it->nglyphs)
9920 {
9921
9922
9923 int single_glyph_width = it->pixel_width / it->nglyphs;
9924 int new_x;
9925 int x_before_this_char = x;
9926 int hpos_before_this_char = it->hpos;
9927
9928 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9929 {
9930 new_x = x + single_glyph_width;
9931
9932
9933 if ((op & MOVE_TO_X) && new_x > to_x)
9934 {
9935 if (BUFFER_POS_REACHED_P ())
9936 {
9937 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9938 goto buffer_pos_reached;
9939 if (atpos_it.sp < 0)
9940 {
9941 SAVE_IT (atpos_it, *it, atpos_data);
9942 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9943 }
9944 }
9945 else
9946 {
9947 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9948 {
9949 it->current_x = x;
9950 result = MOVE_X_REACHED;
9951 break;
9952 }
9953 if (atx_it.sp < 0)
9954 {
9955 SAVE_IT (atx_it, *it, atx_data);
9956 IT_RESET_X_ASCENT_DESCENT (&atx_it);
9957 }
9958 }
9959 }
9960
9961 if (
9962 it->line_wrap != TRUNCATE
9963 && (
9964 new_x > it->last_visible_x
9965
9966
9967 || (new_x == it->last_visible_x
9968 && FRAME_WINDOW_P (it->f)
9969 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
9970 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
9971 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
9972 {
9973 bool moved_forward = false;
9974
9975 if (
9976
9977 it->hpos == 0
9978 || (new_x == it->last_visible_x
9979 && FRAME_WINDOW_P (it->f)))
9980 {
9981 ++it->hpos;
9982 it->current_x = new_x;
9983
9984
9985
9986 if (i == it->nglyphs - 1)
9987 {
9988
9989
9990
9991 if (BUFFER_POS_REACHED_P ())
9992 {
9993 bool can_wrap = true;
9994
9995
9996
9997
9998
9999 if (it->line_wrap == WORD_WRAP
10000 && wrap_it.sp >= 0
10001 && may_wrap
10002 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10003 {
10004 struct it tem_it;
10005 void *tem_data = NULL;
10006
10007 SAVE_IT (tem_it, *it, tem_data);
10008 set_iterator_to_next (it, true);
10009 if (get_next_display_element (it)
10010 && !char_can_wrap_before (it))
10011 can_wrap = false;
10012 RESTORE_IT (it, &tem_it, tem_data);
10013 }
10014 if (it->line_wrap != WORD_WRAP
10015 || wrap_it.sp < 0
10016
10017
10018
10019
10020
10021
10022
10023 || (may_wrap && can_wrap
10024 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10025 {
10026 it->hpos = hpos_before_this_char;
10027 it->current_x = x_before_this_char;
10028 result = MOVE_POS_MATCH_OR_ZV;
10029 break;
10030 }
10031 if (it->line_wrap == WORD_WRAP
10032 && atpos_it.sp < 0)
10033 {
10034 SAVE_IT (atpos_it, *it, atpos_data);
10035 atpos_it.current_x = x_before_this_char;
10036 atpos_it.hpos = hpos_before_this_char;
10037 }
10038 }
10039
10040 prev_method = it->method;
10041 if (it->method == GET_FROM_BUFFER)
10042 prev_pos = IT_CHARPOS (*it);
10043 set_iterator_to_next (it, true);
10044 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10045 SET_TEXT_POS (this_line_min_pos,
10046 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10047
10048
10049
10050
10051
10052
10053
10054 if (!FRAME_WINDOW_P (it->f)
10055 || ((it->bidi_p
10056 && it->bidi_it.paragraph_dir == R2L)
10057 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10058 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10059 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10060 {
10061 if (!get_next_display_element (it))
10062 {
10063 result = MOVE_POS_MATCH_OR_ZV;
10064 break;
10065 }
10066 moved_forward = true;
10067 if (BUFFER_POS_REACHED_P ())
10068 {
10069 if (ITERATOR_AT_END_OF_LINE_P (it))
10070 result = MOVE_POS_MATCH_OR_ZV;
10071 else
10072 result = MOVE_LINE_CONTINUED;
10073 break;
10074 }
10075 if (ITERATOR_AT_END_OF_LINE_P (it)
10076 && (it->line_wrap != WORD_WRAP
10077 || wrap_it.sp < 0
10078 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10079 {
10080 result = MOVE_NEWLINE_OR_CR;
10081 break;
10082 }
10083 }
10084 }
10085 }
10086 else
10087 IT_RESET_X_ASCENT_DESCENT (it);
10088
10089
10090
10091
10092
10093
10094 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10095
10096
10097
10098
10099
10100 && (!moved_forward || char_can_wrap_before (it)))
10101 {
10102
10103
10104 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10105 && atx_it.sp >= 0)
10106 {
10107 RESTORE_IT (it, &atx_it, atx_data);
10108 atpos_it.sp = -1;
10109 atx_it.sp = -1;
10110 result = MOVE_X_REACHED;
10111 break;
10112 }
10113 }
10114 else if (wrap_it.sp >= 0)
10115 {
10116 RESTORE_IT (it, &wrap_it, wrap_data);
10117 atpos_it.sp = -1;
10118 atx_it.sp = -1;
10119 }
10120
10121 move_trace ("move_it_in: continued at %td\n",
10122 IT_CHARPOS (*it));
10123 result = MOVE_LINE_CONTINUED;
10124 break;
10125 }
10126
10127 if (BUFFER_POS_REACHED_P ())
10128 {
10129 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10130 goto buffer_pos_reached;
10131 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10132 {
10133 SAVE_IT (atpos_it, *it, atpos_data);
10134 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10135 }
10136 }
10137
10138 if (new_x > it->first_visible_x)
10139 {
10140
10141
10142 if (line_number_pending)
10143 {
10144 line_number_pending = false;
10145 it->current_x = it->first_visible_x;
10146 maybe_produce_line_number (it);
10147 it->current_x += new_x - it->first_visible_x;
10148 }
10149
10150
10151 ++it->hpos;
10152 }
10153 }
10154
10155 if (result != MOVE_UNDEFINED)
10156 break;
10157 }
10158 else if (BUFFER_POS_REACHED_P ())
10159 {
10160 buffer_pos_reached:
10161 IT_RESET_X_ASCENT_DESCENT (it);
10162 result = MOVE_POS_MATCH_OR_ZV;
10163 break;
10164 }
10165 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10166 {
10167
10168
10169
10170
10171 eassert (it->nglyphs == 0);
10172 result = MOVE_X_REACHED;
10173 break;
10174 }
10175
10176
10177 if (ITERATOR_AT_END_OF_LINE_P (it))
10178 {
10179
10180
10181
10182
10183 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10184 {
10185 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10186 {
10187 if (closest_pos < ZV)
10188 {
10189 RESTORE_IT (it, &ppos_it, ppos_data);
10190
10191
10192 if (closest_pos != to_charpos)
10193 move_it_in_display_line_to (it, closest_pos, -1,
10194 MOVE_TO_POS);
10195 result = MOVE_POS_MATCH_OR_ZV;
10196 }
10197 else
10198 goto buffer_pos_reached;
10199 }
10200 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10201 && IT_CHARPOS (*it) > to_charpos)
10202 goto buffer_pos_reached;
10203 else
10204 result = MOVE_NEWLINE_OR_CR;
10205 }
10206 else
10207 result = MOVE_NEWLINE_OR_CR;
10208
10209
10210
10211
10212 if (it->line_wrap == TRUNCATE
10213 && it->current_x <= it->first_visible_x
10214 && result == MOVE_NEWLINE_OR_CR
10215 && it->char_to_display == '\n')
10216 {
10217 it->max_ascent = it->ascent;
10218 it->max_descent = it->descent;
10219 }
10220
10221
10222
10223 if (result == MOVE_NEWLINE_OR_CR)
10224 it->constrain_row_ascent_descent_p = false;
10225 break;
10226 }
10227
10228 prev_method = it->method;
10229 if (it->method == GET_FROM_BUFFER)
10230 prev_pos = IT_CHARPOS (*it);
10231
10232
10233
10234
10235
10236
10237
10238
10239
10240 bool overwide_wrap_prefix =
10241 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10242 && it->sp > 0 && it->method == GET_FROM_STRETCH
10243 && it->current_x >= it->last_visible_x
10244 && it->continuation_lines_width > 0
10245 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10246
10247
10248 if (!overwide_wrap_prefix)
10249 set_iterator_to_next (it, true);
10250 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10251 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10252 if (IT_CHARPOS (*it) < to_charpos)
10253 saw_smaller_pos = true;
10254 if (it->bidi_p
10255 && (op & MOVE_TO_POS)
10256 && IT_CHARPOS (*it) >= to_charpos
10257 && IT_CHARPOS (*it) < closest_pos)
10258 closest_pos = IT_CHARPOS (*it);
10259
10260
10261
10262 if (it->line_wrap == TRUNCATE
10263 && it->current_x >= it->last_visible_x)
10264 {
10265 if (!FRAME_WINDOW_P (it->f)
10266 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10267 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10268 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10269 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10270 {
10271 bool at_eob_p = false;
10272
10273 if ((at_eob_p = !get_next_display_element (it))
10274 || BUFFER_POS_REACHED_P ()
10275
10276
10277
10278
10279 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10280 && !saw_smaller_pos
10281 && IT_CHARPOS (*it) > to_charpos))
10282 {
10283 if (it->bidi_p
10284 && !BUFFER_POS_REACHED_P ()
10285 && !at_eob_p && closest_pos < ZV)
10286 {
10287 RESTORE_IT (it, &ppos_it, ppos_data);
10288 if (closest_pos != to_charpos)
10289 move_it_in_display_line_to (it, closest_pos, -1,
10290 MOVE_TO_POS);
10291 }
10292 result = MOVE_POS_MATCH_OR_ZV;
10293 break;
10294 }
10295 if (ITERATOR_AT_END_OF_LINE_P (it))
10296 {
10297 result = MOVE_NEWLINE_OR_CR;
10298 break;
10299 }
10300 }
10301 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10302 && !saw_smaller_pos
10303 && IT_CHARPOS (*it) > to_charpos)
10304 {
10305 if (closest_pos < ZV)
10306 {
10307 RESTORE_IT (it, &ppos_it, ppos_data);
10308 if (closest_pos != to_charpos)
10309 move_it_in_display_line_to (it, closest_pos, -1,
10310 MOVE_TO_POS);
10311 }
10312 result = MOVE_POS_MATCH_OR_ZV;
10313 break;
10314 }
10315 result = MOVE_LINE_TRUNCATED;
10316 break;
10317 }
10318 #undef IT_RESET_X_ASCENT_DESCENT
10319 }
10320
10321 #undef BUFFER_POS_REACHED_P
10322
10323
10324
10325
10326
10327
10328 if (result == MOVE_LINE_CONTINUED
10329 && it->line_wrap == WORD_WRAP
10330 && wrap_it.sp >= 0
10331 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10332 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10333 RESTORE_IT (it, &wrap_it, wrap_data);
10334 else if (atpos_it.sp >= 0)
10335 RESTORE_IT (it, &atpos_it, atpos_data);
10336 else if (atx_it.sp >= 0)
10337 RESTORE_IT (it, &atx_it, atx_data);
10338
10339 done:
10340
10341 if (atpos_data)
10342 bidi_unshelve_cache (atpos_data, true);
10343 if (atx_data)
10344 bidi_unshelve_cache (atx_data, true);
10345 if (wrap_data)
10346 bidi_unshelve_cache (wrap_data, true);
10347 if (ppos_data)
10348 bidi_unshelve_cache (ppos_data, true);
10349
10350
10351
10352 it->glyph_row = saved_glyph_row;
10353 return result;
10354 }
10355
10356
10357 void
10358 move_it_in_display_line (struct it *it,
10359 ptrdiff_t to_charpos, int to_x,
10360 enum move_operation_enum op)
10361 {
10362 if (it->line_wrap == WORD_WRAP
10363 && (op & MOVE_TO_X))
10364 {
10365 struct it save_it;
10366 void *save_data = NULL;
10367 int skip;
10368
10369 SAVE_IT (save_it, *it, save_data);
10370 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10371
10372
10373
10374
10375 if (skip == MOVE_LINE_CONTINUED)
10376 {
10377 int prev_x = max (it->current_x - 1, 0);
10378 RESTORE_IT (it, &save_it, save_data);
10379 move_it_in_display_line_to
10380 (it, -1, prev_x, MOVE_TO_X);
10381 }
10382 else
10383 bidi_unshelve_cache (save_data, true);
10384 }
10385 else
10386 move_it_in_display_line_to (it, to_charpos, to_x, op);
10387 }
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403
10404 int
10405 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10406 {
10407 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10408 int line_height, line_start_x = 0, reached = 0;
10409 int max_current_x = 0;
10410 void *backup_data = NULL;
10411 ptrdiff_t orig_charpos = -1;
10412 enum it_method orig_method = NUM_IT_METHODS;
10413
10414 for (;;)
10415 {
10416 orig_charpos = IT_CHARPOS (*it);
10417 orig_method = it->method;
10418 if (op & MOVE_TO_VPOS)
10419 {
10420
10421
10422 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10423 {
10424 if (it->vpos == to_vpos)
10425 {
10426 reached = 1;
10427 break;
10428 }
10429 else
10430 skip = move_it_in_display_line_to (it, -1, -1, 0);
10431 }
10432 else
10433 {
10434
10435
10436 if (it->vpos == to_vpos)
10437 {
10438 reached = 2;
10439 break;
10440 }
10441
10442 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10443
10444 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10445 {
10446 reached = 3;
10447 break;
10448 }
10449 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10450 {
10451
10452 skip = move_it_in_display_line_to (it, to_charpos,
10453 -1, MOVE_TO_POS);
10454 if (skip == MOVE_POS_MATCH_OR_ZV)
10455 {
10456 reached = 4;
10457 break;
10458 }
10459 }
10460 }
10461 }
10462 else if (op & MOVE_TO_Y)
10463 {
10464 struct it it_backup;
10465
10466 if (it->line_wrap == WORD_WRAP)
10467 SAVE_IT (it_backup, *it, backup_data);
10468
10469
10470
10471
10472
10473
10474
10475
10476
10477
10478
10479
10480
10481 skip = move_it_in_display_line_to
10482 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10483 (MOVE_TO_X | (op & MOVE_TO_POS)));
10484
10485
10486 if (skip == MOVE_POS_MATCH_OR_ZV)
10487 reached = 5;
10488 else if (skip == MOVE_X_REACHED)
10489 {
10490
10491
10492
10493
10494 line_height = it->max_ascent + it->max_descent;
10495 if (to_y >= it->current_y
10496 && to_y < it->current_y + line_height)
10497 {
10498 reached = 6;
10499 break;
10500 }
10501 SAVE_IT (it_backup, *it, backup_data);
10502 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10503 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10504 op & MOVE_TO_POS);
10505 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10506 line_height = it->max_ascent + it->max_descent;
10507 move_trace ("move_it: line_height = %d\n", line_height);
10508
10509 if (to_y >= it->current_y
10510 && to_y < it->current_y + line_height)
10511 {
10512
10513
10514
10515
10516
10517
10518
10519
10520 int max_ascent = it->max_ascent;
10521 int max_descent = it->max_descent;
10522
10523 RESTORE_IT (it, &it_backup, backup_data);
10524 it->max_ascent = max_ascent;
10525 it->max_descent = max_descent;
10526 reached = 6;
10527 }
10528 else
10529 {
10530 skip = skip2;
10531 if (skip == MOVE_POS_MATCH_OR_ZV)
10532 {
10533 reached = 7;
10534
10535
10536
10537
10538
10539
10540
10541 if (to_charpos > 0
10542 && IT_CHARPOS (*it) != to_charpos
10543 && ((IT_CHARPOS (it_backup) > to_charpos)
10544 == (IT_CHARPOS (*it) > to_charpos)))
10545 {
10546 int max_ascent = it->max_ascent;
10547 int max_descent = it->max_descent;
10548
10549 RESTORE_IT (it, &it_backup, backup_data);
10550 it->max_ascent = max_ascent;
10551 it->max_descent = max_descent;
10552 }
10553 }
10554 }
10555 }
10556 else
10557 {
10558
10559 line_height = it->max_ascent + it->max_descent;
10560 move_trace ("move_it: line_height = %d\n", line_height);
10561
10562 if (to_y >= it->current_y
10563 && to_y < it->current_y + line_height)
10564 {
10565 if (to_y > it->current_y)
10566 max_current_x = max (it->current_x, max_current_x);
10567
10568
10569
10570
10571
10572 if (skip == MOVE_LINE_CONTINUED
10573 && it->line_wrap == WORD_WRAP)
10574 {
10575 int prev_x = max (it->current_x - 1, 0);
10576 RESTORE_IT (it, &it_backup, backup_data);
10577 skip = move_it_in_display_line_to
10578 (it, -1, prev_x, MOVE_TO_X);
10579 }
10580
10581 reached = 6;
10582 }
10583 }
10584
10585 if (reached)
10586 {
10587 max_current_x = max (it->current_x, max_current_x);
10588 break;
10589 }
10590 }
10591 else if (BUFFERP (it->object)
10592 && (it->method == GET_FROM_BUFFER
10593 || it->method == GET_FROM_STRETCH)
10594 && IT_CHARPOS (*it) >= to_charpos
10595
10596
10597
10598
10599
10600 && !(it->bidi_p
10601 && it->bidi_it.scan_dir == -1))
10602 skip = MOVE_POS_MATCH_OR_ZV;
10603 else
10604 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10605
10606 switch (skip)
10607 {
10608 case MOVE_POS_MATCH_OR_ZV:
10609 max_current_x = max (it->current_x, max_current_x);
10610 reached = 8;
10611 goto out;
10612
10613 case MOVE_NEWLINE_OR_CR:
10614 max_current_x = max (it->current_x, max_current_x);
10615 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10616 it->override_ascent = -1;
10617 set_iterator_to_next (it, true);
10618 it->continuation_lines_width = 0;
10619 break;
10620
10621 case MOVE_LINE_TRUNCATED:
10622 max_current_x = it->last_visible_x;
10623 it->continuation_lines_width = 0;
10624 reseat_at_next_visible_line_start (it, false);
10625 if ((op & MOVE_TO_POS) != 0
10626 && (IT_CHARPOS (*it) > to_charpos
10627 || (IT_CHARPOS (*it) == to_charpos
10628
10629
10630 && to_charpos == ZV
10631 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10632
10633
10634
10635 && (it->sp == 0
10636 || (STRINGP (it->string)
10637 && (it->current.overlay_string_index < 0
10638 || (it->current.overlay_string_index >= 0
10639 && it->current.overlay_string_index
10640 >= it->n_overlay_strings - 1))
10641 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10642 {
10643 reached = 9;
10644 goto out;
10645 }
10646 break;
10647
10648 case MOVE_LINE_CONTINUED:
10649 max_current_x = it->last_visible_x;
10650
10651
10652
10653
10654 if (it->c == '\t')
10655 {
10656 it->continuation_lines_width += it->last_visible_x;
10657
10658
10659
10660 if (it->current_x != it->last_visible_x
10661 && (op & MOVE_TO_VPOS)
10662 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10663 {
10664 line_start_x = it->current_x + it->pixel_width
10665 - it->last_visible_x;
10666 if (FRAME_WINDOW_P (it->f))
10667 {
10668 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10669 struct font *face_font = face->font;
10670
10671
10672
10673
10674
10675
10676
10677 eassert (face_font);
10678 if (face_font)
10679 {
10680 if (line_start_x < face_font->space_width)
10681 line_start_x
10682 += it->tab_width * face_font->space_width;
10683 }
10684 }
10685 set_iterator_to_next (it, false);
10686 }
10687 }
10688 else
10689 {
10690
10691
10692
10693
10694
10695
10696
10697
10698 if (IT_CHARPOS (*it) == orig_charpos
10699 && it->method == orig_method
10700 && orig_method == GET_FROM_BUFFER)
10701 set_iterator_to_next (it, false);
10702 it->continuation_lines_width += it->current_x;
10703 }
10704 break;
10705
10706 default:
10707 emacs_abort ();
10708 }
10709
10710
10711 it->current_x = line_start_x;
10712 line_start_x = 0;
10713 it->hpos = 0;
10714 it->line_number_produced_p = false;
10715 it->current_y += it->max_ascent + it->max_descent;
10716 ++it->vpos;
10717 last_height = it->max_ascent + it->max_descent;
10718 it->max_ascent = it->max_descent = 0;
10719 }
10720
10721 out:
10722
10723
10724
10725
10726
10727
10728 if (!FRAME_WINDOW_P (it->f)
10729 && op & MOVE_TO_POS
10730 && IT_CHARPOS (*it) == to_charpos
10731 && it->what == IT_CHARACTER
10732 && it->nglyphs > 1
10733 && it->line_wrap == WINDOW_WRAP
10734 && it->current_x == it->last_visible_x - 1
10735 && it->c != '\n'
10736 && it->c != '\t'
10737 && it->w->window_end_valid
10738 && it->vpos < it->w->window_end_vpos)
10739 {
10740 it->continuation_lines_width += it->current_x;
10741 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10742 it->current_y += it->max_ascent + it->max_descent;
10743 ++it->vpos;
10744 last_height = it->max_ascent + it->max_descent;
10745 }
10746
10747 if (backup_data)
10748 bidi_unshelve_cache (backup_data, true);
10749
10750 move_trace ("move_it_to: reached %d\n", reached);
10751
10752 return max_current_x;
10753 }
10754
10755
10756
10757
10758
10759
10760
10761
10762
10763
10764
10765 void
10766 move_it_vertically_backward (struct it *it, int dy)
10767 {
10768 int nlines, h;
10769 struct it it2, it3;
10770 void *it2data = NULL, *it3data = NULL;
10771 ptrdiff_t start_pos;
10772 int nchars_per_row
10773 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10774 ptrdiff_t pos_limit;
10775
10776 move_further_back:
10777 eassert (dy >= 0);
10778
10779 start_pos = IT_CHARPOS (*it);
10780
10781
10782 nlines = max (1, dy / default_line_pixel_height (it->w));
10783 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10784 pos_limit = BEGV;
10785 else
10786 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10787
10788
10789
10790
10791 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10792 back_to_previous_visible_line_start (it);
10793
10794
10795
10796
10797
10798 reseat_1 (it, it->current.pos, true);
10799
10800
10801 it->current_x = it->hpos = 0;
10802
10803 it->continuation_lines_width = 0;
10804
10805
10806
10807
10808
10809 SAVE_IT (it2, *it, it2data);
10810 it2.max_ascent = it2.max_descent = 0;
10811 do
10812 {
10813 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10814 MOVE_TO_POS | MOVE_TO_VPOS);
10815 }
10816 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10817
10818
10819
10820
10821
10822
10823 || (it2.method == GET_FROM_STRING
10824 && IT_CHARPOS (it2) == start_pos
10825 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10826 eassert (IT_CHARPOS (*it) >= BEGV);
10827 SAVE_IT (it3, it2, it3data);
10828
10829 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10830 eassert (IT_CHARPOS (*it) >= BEGV);
10831
10832
10833 h = it2.current_y - it->current_y;
10834
10835 nlines = it2.vpos - it->vpos;
10836
10837
10838
10839 it->vpos -= nlines;
10840 it->current_y -= h;
10841
10842 if (dy == 0)
10843 {
10844
10845
10846
10847 RESTORE_IT (it, it, it2data);
10848 if (nlines > 0)
10849 move_it_by_lines (it, nlines);
10850
10851
10852
10853
10854
10855
10856 if (it->bidi_p
10857 && !it->continuation_lines_width
10858 && !STRINGP (it->string)
10859 && IT_CHARPOS (*it) > BEGV
10860 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10861 {
10862 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10863
10864 dec_both (&cp, &bp);
10865 SET_WITH_NARROWED_BEGV (it, cp,
10866 find_newline_no_quit (cp, bp, -1, NULL),
10867 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10868 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10869 }
10870 bidi_unshelve_cache (it3data, true);
10871 }
10872 else
10873 {
10874
10875
10876 int target_y = it->current_y + h - dy;
10877 int y0 = it3.current_y;
10878 int y1;
10879 int line_height;
10880
10881 RESTORE_IT (&it3, &it3, it3data);
10882 y1 = line_bottom_y (&it3);
10883 line_height = y1 - y0;
10884 RESTORE_IT (it, it, it2data);
10885
10886
10887 if (target_y < it->current_y
10888
10889
10890
10891
10892 && (it->current_y - target_y
10893 > min (window_box_height (it->w), line_height * 2 / 3))
10894 && IT_CHARPOS (*it) > BEGV)
10895 {
10896 move_trace (" not far enough -> move_vert %d\n",
10897 target_y - it->current_y);
10898 dy = it->current_y - target_y;
10899 goto move_further_back;
10900 }
10901 else if (target_y >= it->current_y + line_height
10902 && IT_CHARPOS (*it) < ZV)
10903 {
10904
10905
10906
10907
10908
10909
10910
10911
10912 if (!FRAME_WINDOW_P (it->f))
10913 move_it_vertically (it, target_y - it->current_y);
10914 else
10915 {
10916 struct text_pos last_pos;
10917 int last_y, last_vpos;
10918 do
10919 {
10920 last_pos = it->current.pos;
10921 last_y = it->current_y;
10922 last_vpos = it->vpos;
10923 move_it_by_lines (it, 1);
10924 }
10925 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10926 if (it->current_y > target_y)
10927 {
10928 reseat (it, last_pos, true);
10929 it->current_y = last_y;
10930 it->vpos = last_vpos;
10931 }
10932 }
10933 }
10934 }
10935 }
10936
10937
10938
10939
10940
10941
10942 void
10943 move_it_vertically (struct it *it, int dy)
10944 {
10945 if (dy <= 0)
10946 move_it_vertically_backward (it, -dy);
10947 else
10948 {
10949 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
10950 move_it_to (it, ZV, -1, it->current_y + dy, -1,
10951 MOVE_TO_POS | MOVE_TO_Y);
10952 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
10953
10954
10955
10956 if (IT_CHARPOS (*it) == ZV
10957 && ZV > BEGV
10958 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10959 move_it_by_lines (it, 0);
10960 }
10961 }
10962
10963
10964
10965
10966 void
10967 move_it_past_eol (struct it *it)
10968 {
10969 enum move_it_result rc;
10970
10971 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
10972 if (rc == MOVE_NEWLINE_OR_CR)
10973 set_iterator_to_next (it, false);
10974 }
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985 void
10986 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
10987 {
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005 if (dvpos == 0)
11006 {
11007
11008 move_it_vertically_backward (it, 0);
11009
11010 last_height = 0;
11011 }
11012 else if (dvpos > 0)
11013 {
11014 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
11015 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11016 {
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11028 -1, -1, -1, MOVE_TO_POS);
11029 }
11030 }
11031 else
11032 {
11033 struct it it2;
11034 void *it2data = NULL;
11035 ptrdiff_t start_charpos, orig_charpos, i;
11036 int nchars_per_row
11037 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11038 bool hit_pos_limit = false;
11039 ptrdiff_t pos_limit;
11040
11041
11042
11043
11044 dvpos += it->vpos;
11045 orig_charpos = IT_CHARPOS (*it);
11046 move_it_vertically_backward (it, 0);
11047 dvpos -= it->vpos;
11048
11049
11050
11051 start_charpos = IT_CHARPOS (*it);
11052 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11053 pos_limit = BEGV;
11054 else
11055 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11056
11057 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11058 back_to_previous_visible_line_start (it);
11059 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11060 hit_pos_limit = true;
11061 reseat (it, it->current.pos, true);
11062
11063
11064 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11065 {
11066
11067 dvpos += it->vpos;
11068 move_it_vertically_backward (it, 0);
11069 dvpos -= it->vpos;
11070 if (IT_POS_VALID_AFTER_MOVE_P (it))
11071 break;
11072
11073
11074 back_to_previous_visible_line_start (it);
11075 reseat (it, it->current.pos, true);
11076 dvpos--;
11077 }
11078
11079 it->current_x = it->hpos = 0;
11080
11081
11082
11083 SAVE_IT (it2, *it, it2data);
11084 it2.vpos = it2.current_y = 0;
11085 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11086 it->vpos -= it2.vpos;
11087 it->current_y -= it2.current_y;
11088 it->current_x = it->hpos = 0;
11089
11090
11091 if (it2.vpos > -dvpos)
11092 {
11093 int delta = it2.vpos + dvpos;
11094
11095 RESTORE_IT (&it2, &it2, it2data);
11096 SAVE_IT (it2, *it, it2data);
11097 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11098
11099
11100 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11101 RESTORE_IT (it, &it2, it2data);
11102 else
11103 bidi_unshelve_cache (it2data, true);
11104 }
11105 else if (hit_pos_limit && pos_limit > BEGV
11106 && dvpos < 0 && it2.vpos < -dvpos)
11107 {
11108
11109
11110
11111
11112
11113
11114
11115
11116 dvpos += it2.vpos;
11117 RESTORE_IT (it, it, it2data);
11118 for (i = -dvpos; i > 0; --i)
11119 {
11120 back_to_previous_visible_line_start (it);
11121 it->vpos--;
11122 }
11123 reseat_1 (it, it->current.pos, true);
11124 }
11125 else
11126 RESTORE_IT (it, it, it2data);
11127 }
11128 }
11129
11130 int
11131 partial_line_height (struct it *it_origin)
11132 {
11133
11134
11135
11136
11137
11138 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11139 && it_origin->line_wrap == TRUNCATE)
11140 return 0;
11141
11142 int partial_height;
11143 void *it_data = NULL;
11144 struct it it;
11145 SAVE_IT (it, *it_origin, it_data);
11146 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11147 MOVE_TO_POS | MOVE_TO_Y);
11148 if (it.what == IT_EOB)
11149 {
11150 int vis_height = it.last_visible_y - it.current_y;
11151 int height = it.ascent + it.descent;
11152 partial_height = (vis_height < height) ? vis_height : 0;
11153 }
11154 else
11155 {
11156 int last_line_y = it.current_y;
11157 move_it_by_lines (&it, 1);
11158 partial_height = (it.current_y > it.last_visible_y)
11159 ? it.last_visible_y - last_line_y : 0;
11160 }
11161 RESTORE_IT (&it, &it, it_data);
11162 return partial_height;
11163 }
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176 static enum move_it_result
11177 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11178 {
11179 ptrdiff_t nl_bytepos;
11180 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11181 1, &nl_bytepos);
11182 struct text_pos new_pos;
11183 enum move_it_result move_result;
11184
11185 if (nl_pos - IT_CHARPOS (*it) > nchars)
11186 {
11187 SET_TEXT_POS (new_pos,
11188 IT_CHARPOS (*it) + nchars,
11189 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11190 move_result = MOVE_X_REACHED;
11191 }
11192 else
11193 {
11194 if (nl_bytepos < ZV_BYTE
11195 || (nl_bytepos > BEGV_BYTE
11196 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11197 {
11198 nl_pos--;
11199 nl_bytepos--;
11200 move_result = MOVE_NEWLINE_OR_CR;
11201 }
11202 else
11203 move_result = MOVE_POS_MATCH_OR_ZV;
11204 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11205 }
11206 reseat (it, new_pos, false);
11207 return move_result;
11208 }
11209
11210
11211
11212 bool
11213 in_display_vector_p (struct it *it)
11214 {
11215 return (it->method == GET_FROM_DISPLAY_VECTOR
11216 && it->current.dpvec_index > 0
11217 && it->dpvec + it->current.dpvec_index != it->dpend);
11218 }
11219
11220
11221
11222
11223
11224 static Lisp_Object
11225 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11226 Lisp_Object x_limit, Lisp_Object y_limit,
11227 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11228 {
11229 struct window *w = decode_live_window (window);
11230 struct it it;
11231 ptrdiff_t start, end, bpos;
11232 struct text_pos startp;
11233 void *itdata = NULL;
11234 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11235
11236 if (NILP (from))
11237 {
11238 start = BEGV;
11239 bpos = BEGV_BYTE;
11240 }
11241 else if (EQ (from, Qt))
11242 {
11243 start = BEGV;
11244 bpos = BEGV_BYTE;
11245 while (bpos < ZV_BYTE)
11246 {
11247 c = FETCH_BYTE (bpos);
11248 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11249 break;
11250 inc_both (&start, &bpos);
11251 }
11252 while (bpos > BEGV_BYTE)
11253 {
11254 dec_both (&start, &bpos);
11255 c = FETCH_BYTE (bpos);
11256 if (!(c == ' ' || c == '\t'))
11257 break;
11258 }
11259 }
11260 else if (CONSP (from))
11261 {
11262 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11263 bpos = CHAR_TO_BYTE (start);
11264 CHECK_FIXNUM (XCDR (from));
11265 vertical_offset = XFIXNUM (XCDR (from));
11266 }
11267 else
11268 {
11269 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11270 bpos = CHAR_TO_BYTE (start);
11271 }
11272
11273 SET_TEXT_POS (startp, start, bpos);
11274
11275 if (NILP (to))
11276 end = ZV;
11277 else if (EQ (to, Qt))
11278 {
11279 end = ZV;
11280 bpos = ZV_BYTE;
11281 while (bpos > BEGV_BYTE)
11282 {
11283 dec_both (&end, &bpos);
11284 c = FETCH_BYTE (bpos);
11285 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11286 {
11287 inc_both (&end, &bpos);
11288 break;
11289 }
11290 }
11291 while (bpos < ZV_BYTE)
11292 {
11293 c = fetch_char_advance (&end, &bpos);
11294 if (!(c == ' ' || c == '\t'))
11295 break;
11296 }
11297 }
11298 else
11299 end = clip_to_bounds (start, fix_position (to), ZV);
11300
11301 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11302 max_x = XFIXNUM (x_limit);
11303 else if (!NILP (x_limit))
11304 max_x = INT_MAX;
11305
11306 if (NILP (y_limit))
11307 max_y = INT_MAX;
11308 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11309 max_y = XFIXNUM (y_limit);
11310
11311 itdata = bidi_shelve_cache ();
11312
11313 start_display (&it, w, startp);
11314
11315 int start_y = it.current_y;
11316
11317
11318
11319
11320
11321
11322
11323 it.bidi_p = false;
11324
11325 int start_x;
11326 if (vertical_offset != 0)
11327 {
11328 int last_y;
11329 it.current_y = 0;
11330
11331 move_it_by_lines (&it, 0);
11332
11333
11334
11335
11336
11337 if (vertical_offset < 0)
11338 {
11339 while (it.current_y > vertical_offset)
11340 {
11341 last_y = it.current_y;
11342 move_it_vertically_backward (&it,
11343 (abs (vertical_offset)
11344 + it.current_y));
11345
11346 if (it.current_y == last_y)
11347 break;
11348 }
11349 }
11350 else
11351 {
11352 move_it_vertically (&it, vertical_offset);
11353 }
11354
11355 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11356 + WINDOW_HEADER_LINE_HEIGHT (w));
11357 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11358 start_y = it.current_y;
11359 start_x = it.current_x;
11360 }
11361 else
11362 {
11363
11364
11365
11366 reseat_at_previous_visible_line_start (&it);
11367 it.current_x = it.hpos = 0;
11368 if (IT_CHARPOS (it) != start)
11369 {
11370 void *it1data = NULL;
11371 struct it it1;
11372
11373 SAVE_IT (it1, it, it1data);
11374 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11375
11376
11377
11378
11379
11380 if (IT_CHARPOS (it) > start && start > BEGV)
11381 {
11382 ptrdiff_t it1pos = IT_CHARPOS (it1);
11383 int it1_x = it1.current_x;
11384
11385 RESTORE_IT (&it, &it1, it1data);
11386
11387
11388
11389
11390
11391 if (start - 1 > it1pos)
11392 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11393 else
11394 move_it_in_display_line (&it, start, it1_x + 1,
11395 MOVE_TO_POS | MOVE_TO_X);
11396 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11397 start_x = it.current_x;
11398
11399
11400
11401 if (IT_CHARPOS (it) == start - 1)
11402 start_x += it.pixel_width;
11403 }
11404 else
11405 {
11406 start_x = it.current_x;
11407 bidi_unshelve_cache (it1data, true);
11408 }
11409 }
11410 else
11411 start_x = it.current_x;
11412 }
11413
11414
11415 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11416 int to_x = -1;
11417 it.current_y = start_y;
11418
11419
11420 if (FETCH_BYTE (start) == '\n')
11421 it.current_x = 0;
11422 if (!NILP (x_limit))
11423 {
11424 it.last_visible_x = max_x;
11425
11426
11427
11428 move_op |= MOVE_TO_X;
11429 to_x = INT_MAX;
11430 }
11431
11432 void *it2data = NULL;
11433 struct it it2;
11434 SAVE_IT (it2, it, it2data);
11435
11436 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11437
11438
11439
11440
11441
11442 if (IT_CHARPOS (it) > end)
11443 {
11444 end--;
11445 RESTORE_IT (&it, &it2, it2data);
11446 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11447
11448
11449
11450 if (IT_CHARPOS (it) == end)
11451 {
11452 x += it.pixel_width;
11453
11454
11455 if (!NILP (ignore_line_at_end))
11456 doff = (max (it.max_ascent, it.ascent)
11457 + max (it.max_descent, it.descent));
11458 else
11459 {
11460 it.max_ascent = max (it.max_ascent, it.ascent);
11461 it.max_descent = max (it.max_descent, it.descent);
11462 }
11463 }
11464 }
11465 else
11466 bidi_unshelve_cache (it2data, true);
11467
11468 if (!NILP (x_limit))
11469 {
11470
11471 if (x > max_x)
11472 x = max_x;
11473 }
11474
11475
11476
11477
11478 if (it.current_y > start_y)
11479 start_x = 0;
11480
11481
11482
11483 if (!NILP (ignore_line_at_end))
11484 y = (it.current_y + doff
11485 - WINDOW_TAB_LINE_HEIGHT (w)
11486 - WINDOW_HEADER_LINE_HEIGHT (w));
11487 else
11488 y = (it.current_y + it.max_ascent + it.max_descent + doff
11489 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11490
11491
11492 if (y > max_y)
11493 y = max_y;
11494
11495 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11496 && window_wants_tab_line (w))
11497
11498 {
11499 Lisp_Object window_tab_line_format
11500 = window_parameter (w, Qtab_line_format);
11501
11502 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11503 NILP (window_tab_line_format)
11504 ? BVAR (current_buffer, tab_line_format)
11505 : window_tab_line_format);
11506 }
11507
11508 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11509 && window_wants_header_line (w))
11510 {
11511 Lisp_Object window_header_line_format
11512 = window_parameter (w, Qheader_line_format);
11513
11514 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11515 NILP (window_header_line_format)
11516 ? BVAR (current_buffer, header_line_format)
11517 : window_header_line_format);
11518 }
11519
11520 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11521 && window_wants_mode_line (w))
11522 {
11523 Lisp_Object window_mode_line_format
11524 = window_parameter (w, Qmode_line_format);
11525
11526 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11527 NILP (window_mode_line_format)
11528 ? BVAR (current_buffer, mode_line_format)
11529 : window_mode_line_format);
11530 }
11531
11532 bidi_unshelve_cache (itdata, false);
11533
11534 return (!vertical_offset
11535 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11536 : list3i (x - start_x, y, start));
11537 }
11538
11539 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11540 doc:
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595 )
11596 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11597 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11598 {
11599 struct window *w = decode_live_window (window);
11600 struct buffer *b = XBUFFER (w->contents);
11601 struct buffer *old_b = NULL;
11602 Lisp_Object value;
11603
11604 if (b != current_buffer)
11605 {
11606 old_b = current_buffer;
11607 set_buffer_internal_1 (b);
11608 }
11609
11610 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11611 ignore_line_at_end);
11612
11613 if (old_b)
11614 set_buffer_internal_1 (old_b);
11615
11616 return value;
11617 }
11618
11619 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11620 doc:
11621
11622
11623
11624
11625
11626
11627
11628
11629
11630
11631
11632
11633 )
11634 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11635 Lisp_Object y_limit)
11636 {
11637 struct window *w = decode_live_window (window);
11638 struct buffer *b = (NILP (buffer_or_name)
11639 ? current_buffer
11640 : XBUFFER (Fget_buffer (buffer_or_name)));
11641 Lisp_Object buffer, value;
11642 specpdl_ref count = SPECPDL_INDEX ();
11643
11644 XSETBUFFER (buffer, b);
11645
11646
11647
11648
11649 record_unwind_protect (unwind_with_echo_area_buffer,
11650 with_echo_area_buffer_unwind_data (w));
11651
11652 set_buffer_internal_1 (b);
11653
11654 if (!EQ (buffer, w->contents))
11655 {
11656 wset_buffer (w, buffer);
11657 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11658 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11659 }
11660
11661 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11662 Qnil);
11663
11664 unbind_to (count, Qnil);
11665
11666 return value;
11667 }
11668
11669
11670 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11671 Sdisplay__line_is_continued_p, 0, 0, 0,
11672 doc: )
11673 (void)
11674 {
11675 struct buffer *oldb = current_buffer;
11676 struct window *w = XWINDOW (selected_window);
11677 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11678
11679 set_buffer_internal_1 (XBUFFER (w->contents));
11680
11681 if (PT < ZV)
11682 {
11683 struct text_pos startpos;
11684 struct it it;
11685 void *itdata;
11686
11687
11688 Lisp_Object opoint = Fpoint_marker ();
11689
11690
11691
11692 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11693 SET_TEXT_POS (startpos, PT, PT_BYTE);
11694 itdata = bidi_shelve_cache ();
11695 start_display (&it, w, startpos);
11696
11697 if (it.line_wrap != TRUNCATE)
11698 {
11699 it.glyph_row = NULL;
11700 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11701 }
11702 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11703 bidi_unshelve_cache (itdata, false);
11704 }
11705 set_buffer_internal_1 (oldb);
11706
11707 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11708 }
11709
11710
11711
11712
11713
11714
11715
11716
11717 static ptrdiff_t
11718 format_nargs (char const *format)
11719 {
11720 ptrdiff_t nargs = 0;
11721 for (char const *p = format; (p = strchr (p, '%')); p++)
11722 if (p[1] == '%')
11723 p++;
11724 else
11725 nargs++;
11726 return nargs;
11727 }
11728
11729
11730
11731
11732 void
11733 add_to_log (const char *format, ...)
11734 {
11735 va_list ap;
11736 va_start (ap, format);
11737 vadd_to_log (format, ap);
11738 va_end (ap);
11739 }
11740
11741 void
11742 vadd_to_log (char const *format, va_list ap)
11743 {
11744 ptrdiff_t form_nargs = format_nargs (format);
11745 ptrdiff_t nargs = 1 + form_nargs;
11746 Lisp_Object args[10];
11747 eassert (nargs <= ARRAYELTS (args));
11748 AUTO_STRING (args0, format);
11749 args[0] = args0;
11750 for (ptrdiff_t i = 1; i <= nargs; i++)
11751 args[i] = va_arg (ap, Lisp_Object);
11752 Lisp_Object msg = Qnil;
11753 msg = Fformat_message (nargs, args);
11754
11755 ptrdiff_t len = SBYTES (msg) + 1;
11756 USE_SAFE_ALLOCA;
11757 char *buffer = SAFE_ALLOCA (len);
11758 memcpy (buffer, SDATA (msg), len);
11759
11760 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11761 SAFE_FREE ();
11762 }
11763
11764
11765
11766
11767 void
11768 message_log_maybe_newline (void)
11769 {
11770 if (message_log_need_newline)
11771 message_dolog ("", 0, true, false);
11772 }
11773
11774
11775
11776
11777
11778
11779
11780
11781
11782
11783
11784 void
11785 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11786 {
11787 const unsigned char *msg = (const unsigned char *) m;
11788
11789 if (!NILP (Vmemory_full))
11790 return;
11791
11792 if (!NILP (Vmessage_log_max))
11793 {
11794 struct buffer *oldbuf;
11795 Lisp_Object oldpoint, oldbegv, oldzv;
11796 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11797 ptrdiff_t point_at_end = 0;
11798 ptrdiff_t zv_at_end = 0;
11799 Lisp_Object old_deactivate_mark;
11800
11801 old_deactivate_mark = Vdeactivate_mark;
11802 oldbuf = current_buffer;
11803
11804
11805
11806 if (! STRINGP (Vmessages_buffer_name))
11807 Vmessages_buffer_name = build_string ("*Messages*");
11808
11809
11810 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11811 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11812 if (newbuffer
11813 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11814 call0 (intern ("messages-buffer-mode"));
11815
11816 bset_undo_list (current_buffer, Qt);
11817 bset_cache_long_scans (current_buffer, Qnil);
11818
11819 oldpoint = message_dolog_marker1;
11820 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11821 oldbegv = message_dolog_marker2;
11822 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11823 oldzv = message_dolog_marker3;
11824 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11825
11826 if (PT == Z)
11827 point_at_end = 1;
11828 if (ZV == Z)
11829 zv_at_end = 1;
11830
11831 BEGV = BEG;
11832 BEGV_BYTE = BEG_BYTE;
11833 ZV = Z;
11834 ZV_BYTE = Z_BYTE;
11835 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11836
11837
11838
11839 if (multibyte
11840 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11841 {
11842
11843
11844 for (ptrdiff_t i = 0; i < nbytes; )
11845 {
11846 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11847 char work = CHAR_TO_BYTE8 (c);
11848 insert_1_both (&work, 1, 1, true, false, false);
11849 i += char_bytes;
11850 }
11851 }
11852 else if (! multibyte
11853 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11854 {
11855
11856
11857 for (ptrdiff_t i = 0; i < nbytes; i++)
11858 {
11859 int c = make_char_multibyte (msg[i]);
11860 unsigned char str[MAX_MULTIBYTE_LENGTH];
11861 int char_bytes = CHAR_STRING (c, str);
11862 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11863 }
11864 }
11865 else if (nbytes)
11866 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11867 true, false, false);
11868
11869 if (nlflag)
11870 {
11871 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11872 intmax_t dups;
11873
11874
11875
11876
11877
11878 specpdl_ref count = SPECPDL_INDEX ();
11879 specbind (Qinhibit_modification_hooks, Qt);
11880
11881 insert_1_both ("\n", 1, 1, true, false, false);
11882
11883 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11884 this_bol = PT;
11885 this_bol_byte = PT_BYTE;
11886
11887
11888
11889 if (this_bol > BEG)
11890 {
11891 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11892 prev_bol = PT;
11893 prev_bol_byte = PT_BYTE;
11894
11895 dups = message_log_check_duplicate (prev_bol_byte,
11896 this_bol_byte);
11897 if (dups)
11898 {
11899 del_range_both (prev_bol, prev_bol_byte,
11900 this_bol, this_bol_byte, false);
11901 if (dups > 1)
11902 {
11903 char dupstr[sizeof " [ times]"
11904 + INT_STRLEN_BOUND (dups)];
11905
11906
11907
11908 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11909 dups);
11910 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11911 insert_1_both (dupstr, duplen, duplen,
11912 true, false, true);
11913 }
11914 }
11915 }
11916
11917
11918
11919
11920
11921 if (FIXNATP (Vmessage_log_max))
11922 {
11923 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11924 -XFIXNAT (Vmessage_log_max) - 1, false);
11925 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11926 }
11927
11928 unbind_to (count, Qnil);
11929 }
11930 BEGV = marker_position (oldbegv);
11931 BEGV_BYTE = marker_byte_position (oldbegv);
11932
11933 if (zv_at_end)
11934 {
11935 ZV = Z;
11936 ZV_BYTE = Z_BYTE;
11937 }
11938 else
11939 {
11940 ZV = marker_position (oldzv);
11941 ZV_BYTE = marker_byte_position (oldzv);
11942 }
11943
11944 if (point_at_end)
11945 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11946 else
11947
11948
11949 TEMP_SET_PT_BOTH (marker_position (oldpoint),
11950 marker_byte_position (oldpoint));
11951
11952 unchain_marker (XMARKER (oldpoint));
11953 unchain_marker (XMARKER (oldbegv));
11954 unchain_marker (XMARKER (oldzv));
11955
11956
11957
11958
11959
11960
11961
11962 windows_or_buffers_changed = old_windows_or_buffers_changed;
11963 bset_redisplay (current_buffer);
11964
11965 set_buffer_internal (oldbuf);
11966
11967 message_log_need_newline = !nlflag;
11968 Vdeactivate_mark = old_deactivate_mark;
11969 }
11970 }
11971
11972
11973
11974
11975
11976
11977
11978
11979 static intmax_t
11980 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
11981 {
11982 ptrdiff_t i;
11983 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
11984 bool seen_dots = false;
11985 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
11986 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
11987
11988 for (i = 0; i < len; i++)
11989 {
11990 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
11991 seen_dots = true;
11992 if (p1[i] != p2[i])
11993 return seen_dots;
11994 }
11995 p1 += len;
11996 if (*p1 == '\n')
11997 return 2;
11998 if (*p1++ == ' ' && *p1++ == '[')
11999 {
12000 char *pend;
12001 intmax_t n = strtoimax ((char *) p1, &pend, 10);
12002 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
12003 return n + 1;
12004 }
12005 return 0;
12006 }
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016 void
12017 message3 (Lisp_Object m)
12018 {
12019 clear_message (true, true);
12020 cancel_echoing ();
12021
12022
12023 message_log_maybe_newline ();
12024 if (STRINGP (m))
12025 {
12026 ptrdiff_t nbytes = SBYTES (m);
12027 bool multibyte = STRING_MULTIBYTE (m);
12028 char *buffer;
12029 USE_SAFE_ALLOCA;
12030 SAFE_ALLOCA_STRING (buffer, m);
12031 message_dolog (buffer, nbytes, true, multibyte);
12032 SAFE_FREE ();
12033 }
12034 if (! inhibit_message)
12035 message3_nolog (m);
12036 }
12037
12038
12039
12040 static void
12041 message_to_stderr (Lisp_Object m)
12042 {
12043 if (noninteractive_need_newline)
12044 {
12045 noninteractive_need_newline = false;
12046 errputc ('\n');
12047 }
12048 if (STRINGP (m))
12049 {
12050 Lisp_Object coding_system = Vlocale_coding_system;
12051 Lisp_Object s;
12052
12053 if (!NILP (Vcoding_system_for_write))
12054 coding_system = Vcoding_system_for_write;
12055 if (!NILP (coding_system))
12056 s = code_convert_string_norecord (m, coding_system, true);
12057 else
12058 s = m;
12059
12060 errwrite (SDATA (s), SBYTES (s));
12061 }
12062 if (STRINGP (m) || !cursor_in_echo_area)
12063 errputc ('\n');
12064 }
12065
12066
12067
12068
12069
12070
12071 void
12072 message3_nolog (Lisp_Object m)
12073 {
12074 struct frame *sf = SELECTED_FRAME ();
12075
12076 if (FRAME_INITIAL_P (sf))
12077 message_to_stderr (m);
12078
12079
12080
12081 else if (INTERACTIVE && sf->glyphs_initialized_p)
12082 {
12083
12084
12085 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12086 Lisp_Object frame = XWINDOW (mini_window)->frame;
12087 struct frame *f = XFRAME (frame);
12088
12089 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12090 Fmake_frame_visible (frame);
12091
12092 if (STRINGP (m) && SCHARS (m) > 0)
12093 {
12094 set_message (m);
12095 if (minibuffer_auto_raise)
12096 Fraise_frame (frame);
12097
12098
12099 echo_message_buffer = Qnil;
12100 }
12101 else
12102 clear_message (true, true);
12103
12104 do_pending_window_change (false);
12105 echo_area_display (true);
12106 do_pending_window_change (false);
12107 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12108 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12109 }
12110 }
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121 void
12122 message1 (const char *m)
12123 {
12124 message3 (m ? build_unibyte_string (m) : Qnil);
12125 }
12126
12127
12128
12129
12130 void
12131 message1_nolog (const char *m)
12132 {
12133 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12134 }
12135
12136
12137
12138
12139 void
12140 message_with_string (const char *m, Lisp_Object string, bool log)
12141 {
12142 CHECK_STRING (string);
12143
12144 bool need_message;
12145 if (noninteractive)
12146 need_message = !!m;
12147 else if (!INTERACTIVE)
12148 need_message = false;
12149 else
12150 {
12151
12152
12153
12154 Lisp_Object mini_window;
12155 struct frame *f, *sf = SELECTED_FRAME ();
12156
12157
12158
12159 mini_window = FRAME_MINIBUF_WINDOW (sf);
12160 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12161
12162
12163
12164
12165 need_message = f->glyphs_initialized_p;
12166 }
12167
12168 if (need_message)
12169 {
12170 AUTO_STRING (fmt, m);
12171 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12172
12173 if (noninteractive)
12174 message_to_stderr (msg);
12175 else
12176 {
12177 if (log)
12178 message3 (msg);
12179 else
12180 message3_nolog (msg);
12181
12182
12183
12184 message_buf_print = false;
12185 }
12186 }
12187 }
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12201 vmessage (const char *m, va_list ap)
12202 {
12203 if (noninteractive)
12204 {
12205 if (m)
12206 {
12207 if (noninteractive_need_newline)
12208 putc ('\n', stderr);
12209 noninteractive_need_newline = false;
12210 vfprintf (stderr, m, ap);
12211 if (!cursor_in_echo_area)
12212 putc ('\n', stderr);
12213 fflush (stderr);
12214 }
12215 }
12216 else if (INTERACTIVE)
12217 {
12218
12219
12220
12221 Lisp_Object mini_window;
12222 struct frame *f, *sf = SELECTED_FRAME ();
12223
12224
12225
12226 mini_window = FRAME_MINIBUF_WINDOW (sf);
12227 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12228
12229
12230
12231
12232 if (f->glyphs_initialized_p)
12233 {
12234 if (m)
12235 {
12236 ptrdiff_t len;
12237 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12238 USE_SAFE_ALLOCA;
12239 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12240
12241 len = doprnt (message_buf, maxsize, m, 0, ap);
12242
12243 message3 (make_string (message_buf, len));
12244 SAFE_FREE ();
12245 }
12246 else
12247 message1 (0);
12248
12249
12250
12251 message_buf_print = false;
12252 }
12253 }
12254 }
12255
12256
12257 void
12258 message (const char *m, ...)
12259 {
12260 va_list ap;
12261 va_start (ap, m);
12262 vmessage (m, ap);
12263 va_end (ap);
12264 }
12265
12266
12267
12268
12269
12270
12271 void
12272 update_echo_area (void)
12273 {
12274 if (!NILP (echo_area_buffer[0]))
12275 {
12276 Lisp_Object string;
12277 string = Fcurrent_message ();
12278 message3 (string);
12279 }
12280 }
12281
12282
12283
12284
12285
12286 static void
12287 ensure_echo_area_buffers (void)
12288 {
12289 for (int i = 0; i < 2; i++)
12290 if (!BUFFERP (echo_buffer[i])
12291 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12292 {
12293 Lisp_Object old_buffer = echo_buffer[i];
12294 static char const name_fmt[] = " *Echo Area %d*";
12295 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12296 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12297 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12298 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12299
12300
12301
12302
12303 for (int j = 0; j < 2; j++)
12304 if (EQ (old_buffer, echo_area_buffer[j]))
12305 echo_area_buffer[j] = echo_buffer[i];
12306 }
12307 }
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326 static bool
12327 with_echo_area_buffer (struct window *w, int which,
12328 bool (*fn) (void *, Lisp_Object),
12329 void *a1, Lisp_Object a2)
12330 {
12331 Lisp_Object buffer;
12332 bool this_one, the_other, clear_buffer_p, rc;
12333 specpdl_ref count = SPECPDL_INDEX ();
12334
12335
12336 ensure_echo_area_buffers ();
12337
12338 clear_buffer_p = false;
12339
12340 if (which == 0)
12341 this_one = false, the_other = true;
12342 else if (which > 0)
12343 this_one = true, the_other = false;
12344 else
12345 {
12346 this_one = false, the_other = true;
12347 clear_buffer_p = true;
12348
12349
12350
12351 if (!NILP (echo_area_buffer[this_one])
12352 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12353 echo_area_buffer[this_one] = Qnil;
12354 }
12355
12356
12357
12358 if (NILP (echo_area_buffer[this_one]))
12359 {
12360 echo_area_buffer[this_one]
12361 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12362 ? echo_buffer[the_other]
12363 : echo_buffer[this_one]);
12364 clear_buffer_p = true;
12365 }
12366
12367 buffer = echo_area_buffer[this_one];
12368
12369
12370
12371 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12372 cancel_echoing ();
12373
12374 record_unwind_protect (unwind_with_echo_area_buffer,
12375 with_echo_area_buffer_unwind_data (w));
12376
12377
12378
12379
12380
12381
12382
12383
12384 set_buffer_internal_1 (XBUFFER (buffer));
12385 if (w)
12386 {
12387 wset_buffer (w, buffer);
12388 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12389 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12390 }
12391
12392 bset_undo_list (current_buffer, Qt);
12393 bset_read_only (current_buffer, Qnil);
12394 specbind (Qinhibit_read_only, Qt);
12395 specbind (Qinhibit_modification_hooks, Qt);
12396
12397 if (clear_buffer_p && Z > BEG)
12398 del_range (BEG, Z);
12399
12400 eassert (BEGV >= BEG);
12401 eassert (ZV <= Z && ZV >= BEGV);
12402
12403 rc = fn (a1, a2);
12404
12405 eassert (BEGV >= BEG);
12406 eassert (ZV <= Z && ZV >= BEGV);
12407
12408 unbind_to (count, Qnil);
12409 return rc;
12410 }
12411
12412
12413
12414
12415
12416 static Lisp_Object
12417 with_echo_area_buffer_unwind_data (struct window *w)
12418 {
12419 int i = 0;
12420 Lisp_Object vector, tmp;
12421
12422
12423
12424 vector = Vwith_echo_area_save_vector;
12425 Vwith_echo_area_save_vector = Qnil;
12426
12427 if (NILP (vector))
12428 vector = make_nil_vector (11);
12429
12430 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12431 ASET (vector, i, Vdeactivate_mark); ++i;
12432 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12433
12434 if (w)
12435 {
12436 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12437 ASET (vector, i, w->contents); ++i;
12438 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12439 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12440 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12441 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12442 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12443 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12444 }
12445 else
12446 {
12447 int end = i + 8;
12448 for (; i < end; ++i)
12449 ASET (vector, i, Qnil);
12450 }
12451
12452 eassert (i == ASIZE (vector));
12453 return vector;
12454 }
12455
12456
12457
12458
12459
12460 static void
12461 unwind_with_echo_area_buffer (Lisp_Object vector)
12462 {
12463 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12464 Vdeactivate_mark = AREF (vector, 1);
12465 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12466
12467 if (WINDOWP (AREF (vector, 3)))
12468 {
12469 struct window *w;
12470 Lisp_Object buffer;
12471
12472 w = XWINDOW (AREF (vector, 3));
12473 buffer = AREF (vector, 4);
12474
12475 wset_buffer (w, buffer);
12476 set_marker_restricted_both (w->pointm, buffer,
12477 XFIXNAT (AREF (vector, 5)),
12478 XFIXNAT (AREF (vector, 6)));
12479 set_marker_restricted_both (w->old_pointm, buffer,
12480 XFIXNAT (AREF (vector, 7)),
12481 XFIXNAT (AREF (vector, 8)));
12482 set_marker_restricted_both (w->start, buffer,
12483 XFIXNAT (AREF (vector, 9)),
12484 XFIXNAT (AREF (vector, 10)));
12485 }
12486
12487 Vwith_echo_area_save_vector = vector;
12488 }
12489
12490
12491
12492
12493
12494 void
12495 setup_echo_area_for_printing (bool multibyte_p)
12496 {
12497
12498 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12499 Fkill_emacs (Qnil, Qnil);
12500
12501 ensure_echo_area_buffers ();
12502
12503 if (!message_buf_print)
12504 {
12505
12506
12507 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12508 echo_area_buffer[0] = echo_buffer[1];
12509 else
12510 echo_area_buffer[0] = echo_buffer[0];
12511
12512
12513 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12514 bset_truncate_lines (current_buffer, Qnil);
12515
12516 if (Z > BEG)
12517 {
12518 specpdl_ref count = SPECPDL_INDEX ();
12519 specbind (Qinhibit_read_only, Qt);
12520
12521 del_range (BEG, Z);
12522 unbind_to (count, Qnil);
12523 }
12524 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12525
12526
12527
12528
12529
12530
12531
12532 if (unibyte_display_via_language_environment
12533 && !multibyte_p
12534 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12535 Fset_buffer_multibyte (Qnil);
12536 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12537 Fset_buffer_multibyte (Qt);
12538
12539
12540 if (minibuffer_auto_raise)
12541 {
12542 struct frame *sf = SELECTED_FRAME ();
12543 Lisp_Object mini_window;
12544 mini_window = FRAME_MINIBUF_WINDOW (sf);
12545 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12546 }
12547
12548 message_log_maybe_newline ();
12549 message_buf_print = true;
12550 }
12551 else
12552 {
12553 if (NILP (echo_area_buffer[0]))
12554 {
12555 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12556 echo_area_buffer[0] = echo_buffer[1];
12557 else
12558 echo_area_buffer[0] = echo_buffer[0];
12559 }
12560
12561 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12562 {
12563
12564 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12565 bset_truncate_lines (current_buffer, Qnil);
12566 }
12567 }
12568 }
12569
12570
12571
12572
12573
12574
12575
12576 static bool
12577 display_echo_area (struct window *w)
12578 {
12579 bool no_message_p, window_height_changed_p;
12580
12581
12582
12583
12584
12585
12586 specpdl_ref count = inhibit_garbage_collection ();
12587
12588
12589
12590
12591
12592 bool i = display_last_displayed_message_p;
12593
12594
12595
12596 no_message_p = NILP (echo_area_buffer[i]);
12597
12598 window_height_changed_p
12599 = with_echo_area_buffer (w, display_last_displayed_message_p,
12600 display_echo_area_1, w, Qnil);
12601
12602 if (no_message_p)
12603 echo_area_buffer[i] = Qnil;
12604
12605 unbind_to (count, Qnil);
12606 return window_height_changed_p;
12607 }
12608
12609
12610
12611
12612
12613
12614
12615
12616 static bool
12617 display_echo_area_1 (void *a1, Lisp_Object a2)
12618 {
12619 struct window *w = a1;
12620 Lisp_Object window;
12621 struct text_pos start;
12622
12623
12624
12625
12626 forget_escape_and_glyphless_faces ();
12627
12628
12629
12630
12631 bool window_height_changed_p = resize_mini_window (w, false);
12632
12633
12634 SET_TEXT_POS_FROM_MARKER (start, w->start);
12635
12636
12637 clear_glyph_matrix (w->desired_matrix);
12638 XSETWINDOW (window, w);
12639 void *itdata = bidi_shelve_cache ();
12640 try_window (window, start, 0);
12641 bidi_unshelve_cache (itdata, false);
12642
12643 return window_height_changed_p;
12644 }
12645
12646
12647
12648
12649
12650
12651 void
12652 resize_echo_area_exactly (void)
12653 {
12654 if (BUFFERP (echo_area_buffer[0])
12655 && WINDOWP (echo_area_window))
12656 {
12657 struct window *w = XWINDOW (echo_area_window);
12658 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12659 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12660 w, resize_exactly);
12661 if (resized_p)
12662 {
12663 windows_or_buffers_changed = 42;
12664 update_mode_lines = 30;
12665 redisplay_internal ();
12666 }
12667 }
12668 }
12669
12670
12671
12672
12673
12674
12675
12676
12677 static bool
12678 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12679 {
12680 return resize_mini_window (a1, !NILP (exactly));
12681 }
12682
12683
12684
12685
12686
12687
12688
12689
12690
12691
12692
12693
12694
12695 bool
12696 resize_mini_window (struct window *w, bool exact_p)
12697 {
12698 struct frame *f = XFRAME (w->frame);
12699 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12700
12701 eassert (MINI_WINDOW_P (w));
12702
12703
12704
12705
12706
12707
12708
12709 if (!NILP (Vinhibit_redisplay))
12710 return false;
12711
12712
12713 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12714 set_marker_both (w->start, w->contents,
12715 BUF_BEGV (XBUFFER (w->contents)),
12716 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12717
12718
12719 if ((NILP (Vresize_mini_windows)
12720 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12721 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12722 return false;
12723
12724 if (FRAME_MINIBUF_ONLY_P (f))
12725 {
12726 if (!NILP (resize_mini_frames))
12727 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12728 }
12729 else
12730 {
12731 struct it it;
12732 int unit = FRAME_LINE_HEIGHT (f);
12733 int height, max_height;
12734 struct text_pos start;
12735 struct buffer *old_current_buffer = NULL;
12736 int windows_height = FRAME_INNER_HEIGHT (f);
12737
12738 if (current_buffer != XBUFFER (w->contents))
12739 {
12740 old_current_buffer = current_buffer;
12741 set_buffer_internal (XBUFFER (w->contents));
12742 }
12743
12744 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12745
12746
12747 if (FLOATP (Vmax_mini_window_height))
12748 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12749 else if (FIXNUMP (Vmax_mini_window_height))
12750 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12751 else
12752 max_height = windows_height / 4;
12753
12754
12755 max_height = clip_to_bounds (unit, max_height, windows_height);
12756
12757
12758 last_height = 0;
12759 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12760
12761
12762 if (it.max_ascent == 0 && it.max_descent == 0)
12763 {
12764 height = it.current_y;
12765
12766
12767
12768
12769
12770 if (!(it.line_wrap == TRUNCATE
12771 && it.current_x <= it.first_visible_x
12772 && ZV_BYTE > 1
12773 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12774 height += last_height;
12775 }
12776 else
12777 height = it.current_y + it.max_ascent + it.max_descent;
12778 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12779
12780
12781 if (height > max_height)
12782 {
12783 height = (max_height / unit) * unit;
12784 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12785 {
12786 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12787 move_it_vertically_backward (&it, height - unit);
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797 move_it_by_lines (&it, 0);
12798 start = it.current.pos;
12799
12800
12801 w->start_at_line_beg = false;
12802 SET_MARKER_FROM_TEXT_POS (w->start, start);
12803 }
12804 }
12805 else
12806 {
12807 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12808 SET_MARKER_FROM_TEXT_POS (w->start, start);
12809 }
12810
12811 if (EQ (Vresize_mini_windows, Qgrow_only))
12812 {
12813
12814
12815 if (height > old_height)
12816 grow_mini_window (w, height - old_height);
12817 else if (height < old_height && (exact_p || BEGV == ZV))
12818 shrink_mini_window (w);
12819 }
12820 else if (height != old_height)
12821
12822 grow_mini_window (w, height - old_height);
12823
12824 if (old_current_buffer)
12825 set_buffer_internal (old_current_buffer);
12826 }
12827
12828 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12829 }
12830
12831
12832
12833
12834
12835 Lisp_Object
12836 current_message (void)
12837 {
12838 Lisp_Object msg;
12839
12840 if (!BUFFERP (echo_area_buffer[0]))
12841 msg = Qnil;
12842 else
12843 {
12844 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12845 if (NILP (msg))
12846 echo_area_buffer[0] = Qnil;
12847 }
12848
12849 return msg;
12850 }
12851
12852
12853 static bool
12854 current_message_1 (void *a1, Lisp_Object a2)
12855 {
12856 Lisp_Object *msg = a1;
12857
12858 if (Z > BEG)
12859 *msg = make_buffer_string (BEG, Z, true);
12860 else
12861 *msg = Qnil;
12862 return false;
12863 }
12864
12865
12866
12867
12868
12869
12870
12871 bool
12872 push_message (void)
12873 {
12874 Lisp_Object msg = current_message ();
12875 Vmessage_stack = Fcons (msg, Vmessage_stack);
12876 return STRINGP (msg);
12877 }
12878
12879
12880
12881
12882 void
12883 restore_message (void)
12884 {
12885 eassert (CONSP (Vmessage_stack));
12886 message3_nolog (XCAR (Vmessage_stack));
12887 }
12888
12889
12890
12891
12892 void
12893 pop_message_unwind (void)
12894 {
12895
12896 eassert (CONSP (Vmessage_stack));
12897 Vmessage_stack = XCDR (Vmessage_stack);
12898 }
12899
12900
12901
12902
12903
12904
12905 void
12906 check_message_stack (void)
12907 {
12908 if (!NILP (Vmessage_stack))
12909 emacs_abort ();
12910 }
12911
12912 void
12913 clear_message_stack (void)
12914 {
12915 Vmessage_stack = Qnil;
12916 }
12917
12918
12919
12920
12921 void
12922 truncate_echo_area (ptrdiff_t nchars)
12923 {
12924 if (nchars == 0)
12925 echo_area_buffer[0] = Qnil;
12926 else if (!noninteractive
12927 && INTERACTIVE
12928 && !NILP (echo_area_buffer[0]))
12929 {
12930 struct frame *sf = SELECTED_FRAME ();
12931
12932
12933
12934 if (sf->glyphs_initialized_p)
12935 with_echo_area_buffer (0, 0, truncate_message_1,
12936 (void *) (intptr_t) nchars, Qnil);
12937 }
12938 }
12939
12940
12941
12942
12943
12944 static bool
12945 truncate_message_1 (void *a1, Lisp_Object a2)
12946 {
12947 intptr_t nchars = (intptr_t) a1;
12948 if (BEG + nchars < Z)
12949 del_range (BEG + nchars, Z);
12950 if (Z == BEG)
12951 echo_area_buffer[0] = Qnil;
12952 return false;
12953 }
12954
12955 extern intptr_t garbage_collection_inhibited;
12956
12957
12958
12959 static void
12960 set_message (Lisp_Object string)
12961 {
12962 Lisp_Object message = Qnil;
12963
12964 eassert (STRINGP (string));
12965
12966 if (FUNCTIONP (Vset_message_function)
12967
12968
12969
12970 && !garbage_collection_inhibited)
12971 {
12972 specpdl_ref count = SPECPDL_INDEX ();
12973 specbind (Qinhibit_quit, Qt);
12974 message = safe_call1 (Vset_message_function, string);
12975 unbind_to (count, Qnil);
12976
12977 if (STRINGP (message))
12978 {
12979 string = message;
12980 message = Qnil;
12981 }
12982 }
12983
12984 if (NILP (message))
12985 {
12986 message_enable_multibyte = STRING_MULTIBYTE (string);
12987
12988 with_echo_area_buffer (0, -1, set_message_1, 0, string);
12989 message_buf_print = false;
12990 help_echo_showing_p = false;
12991 }
12992
12993 if (STRINGP (Vdebug_on_message)
12994 && STRINGP (string)
12995 && fast_string_match (Vdebug_on_message, string) >= 0)
12996 call_debugger (list2 (Qerror, string));
12997 }
12998
12999
13000
13001
13002
13003
13004 static bool
13005 set_message_1 (void *a1, Lisp_Object string)
13006 {
13007 eassert (STRINGP (string));
13008
13009
13010
13011
13012
13013
13014 if (!message_enable_multibyte
13015 && unibyte_display_via_language_environment
13016 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13017 Fset_buffer_multibyte (Qnil);
13018 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13019 Fset_buffer_multibyte (Qt);
13020
13021 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13022 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13023 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13024
13025
13026 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13027
13028
13029
13030
13031 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13032
13033 return false;
13034 }
13035
13036
13037
13038
13039
13040 void
13041 clear_message (bool current_p, bool last_displayed_p)
13042 {
13043 Lisp_Object preserve = Qnil;
13044
13045 if (current_p)
13046 {
13047 if (FUNCTIONP (Vclear_message_function)
13048
13049 && !garbage_collection_inhibited)
13050 {
13051 specpdl_ref count = SPECPDL_INDEX ();
13052 specbind (Qinhibit_quit, Qt);
13053 preserve = safe_call (1, Vclear_message_function);
13054 unbind_to (count, Qnil);
13055 }
13056
13057 if (!EQ (preserve, Qdont_clear_message))
13058 {
13059 echo_area_buffer[0] = Qnil;
13060 message_cleared_p = true;
13061 }
13062 }
13063
13064 if (last_displayed_p)
13065 echo_area_buffer[1] = Qnil;
13066
13067 message_buf_print = false;
13068 }
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
13079 static void
13080 clear_garbaged_frames (void)
13081 {
13082 if (frame_garbaged)
13083 {
13084 Lisp_Object tail, frame;
13085 struct frame *sf = SELECTED_FRAME ();
13086
13087 FOR_EACH_FRAME (tail, frame)
13088 {
13089 struct frame *f = XFRAME (frame);
13090
13091 if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
13092 {
13093 if (f->resized_p
13094
13095
13096
13097
13098
13099 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13100 redraw_frame (f);
13101 else
13102 clear_current_matrices (f);
13103
13104 #ifdef HAVE_WINDOW_SYSTEM
13105 if (FRAME_WINDOW_P (f)
13106 && FRAME_RIF (f)->clear_under_internal_border)
13107 FRAME_RIF (f)->clear_under_internal_border (f);
13108 #endif
13109 fset_redisplay (f);
13110 f->garbaged = false;
13111 f->resized_p = false;
13112 }
13113 }
13114
13115 frame_garbaged = false;
13116 }
13117 }
13118
13119
13120
13121
13122
13123 static void
13124 echo_area_display (bool update_frame_p)
13125 {
13126 Lisp_Object mini_window;
13127 struct window *w;
13128 struct frame *f;
13129 bool window_height_changed_p = false;
13130 struct frame *sf = SELECTED_FRAME ();
13131
13132 mini_window = FRAME_MINIBUF_WINDOW (sf);
13133 if (NILP (mini_window))
13134 return;
13135
13136 w = XWINDOW (mini_window);
13137 f = XFRAME (WINDOW_FRAME (w));
13138
13139
13140 if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
13141 return;
13142
13143 #ifdef HAVE_WINDOW_SYSTEM
13144
13145
13146
13147 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13148 return;
13149 #endif
13150
13151
13152 clear_garbaged_frames ();
13153
13154 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13155 {
13156 echo_area_window = mini_window;
13157 window_height_changed_p = display_echo_area (w);
13158 w->must_be_updated_p = true;
13159
13160
13161
13162
13163
13164 if (update_frame_p && !redisplaying_p)
13165 {
13166 int n = 0;
13167
13168
13169
13170
13171
13172
13173 if (!display_completed)
13174 {
13175 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13176
13177 #ifdef HAVE_WINDOW_SYSTEM
13178 if (FRAME_WINDOW_P (f)
13179 && FRAME_RIF (f)->clear_under_internal_border)
13180 FRAME_RIF (f)->clear_under_internal_border (f);
13181 #endif
13182 }
13183
13184 if (window_height_changed_p
13185
13186
13187 && !NILP (Vrun_hooks))
13188 {
13189
13190
13191
13192 specpdl_ref count = SPECPDL_INDEX ();
13193 specbind (Qredisplay_dont_pause, Qt);
13194 fset_redisplay (f);
13195 redisplay_internal ();
13196 unbind_to (count, Qnil);
13197 }
13198 else if (FRAME_WINDOW_P (f) && n == 0)
13199 {
13200
13201
13202
13203 update_single_window (w);
13204 flush_frame (f);
13205 }
13206 else
13207 update_frame (f, true, true);
13208
13209
13210
13211
13212 if (cursor_in_echo_area)
13213 wset_redisplay (XWINDOW (mini_window));
13214 }
13215 }
13216 else if (!EQ (mini_window, selected_window))
13217 wset_redisplay (XWINDOW (mini_window));
13218
13219
13220 echo_area_buffer[1] = echo_area_buffer[0];
13221
13222 echo_message_buffer = Qnil;
13223
13224
13225
13226
13227 if (EQ (mini_window, selected_window))
13228 CHARPOS (this_line_start_pos) = 0;
13229
13230 if (window_height_changed_p)
13231 {
13232 fset_redisplay (f);
13233
13234
13235
13236
13237
13238 clear_garbaged_frames ();
13239 }
13240 }
13241
13242
13243
13244 static bool
13245 window_buffer_changed (struct window *w)
13246 {
13247 struct buffer *b = XBUFFER (w->contents);
13248
13249 eassert (BUFFER_LIVE_P (b));
13250
13251 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13252 }
13253
13254
13255
13256 static bool
13257 mode_line_update_needed (struct window *w)
13258 {
13259 return (w->column_number_displayed != -1
13260 && !(PT == w->last_point && !window_outdated (w))
13261 && (w->column_number_displayed != current_column ()));
13262 }
13263
13264
13265
13266
13267 static bool
13268 window_frozen_p (struct window *w)
13269 {
13270 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13271 {
13272 Lisp_Object window;
13273
13274 XSETWINDOW (window, w);
13275 if (MINI_WINDOW_P (w))
13276 return false;
13277 else if (EQ (window, selected_window))
13278 return false;
13279 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13280 && EQ (window, Vminibuf_scroll_window))
13281
13282 return false;
13283 else
13284 return true;
13285 }
13286 return false;
13287 }
13288
13289
13290
13291
13292
13293
13294
13295
13296
13297 static char *mode_line_noprop_buf;
13298
13299
13300
13301 static char *mode_line_noprop_buf_end;
13302 static char *mode_line_noprop_ptr;
13303
13304 #define MODE_LINE_NOPROP_LEN(start) \
13305 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13306
13307 static enum {
13308 MODE_LINE_DISPLAY = 0,
13309 MODE_LINE_TITLE,
13310 MODE_LINE_NOPROP,
13311 MODE_LINE_STRING
13312 } mode_line_target;
13313
13314
13315
13316 static Lisp_Object mode_line_proptrans_alist;
13317
13318
13319 static Lisp_Object mode_line_string_list;
13320
13321
13322 static Lisp_Object mode_line_string_face;
13323 static Lisp_Object mode_line_string_face_prop;
13324
13325
13326
13327
13328 static Lisp_Object Vmode_line_unwind_vector;
13329
13330 static Lisp_Object
13331 format_mode_line_unwind_data (struct frame *target_frame,
13332 struct buffer *obuf,
13333 Lisp_Object owin,
13334 bool save_proptrans)
13335 {
13336 Lisp_Object vector, tmp;
13337
13338
13339
13340 vector = Vmode_line_unwind_vector;
13341 Vmode_line_unwind_vector = Qnil;
13342
13343 if (NILP (vector))
13344 vector = make_nil_vector (12);
13345
13346 ASET (vector, 0, make_fixnum (mode_line_target));
13347 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13348 ASET (vector, 2, mode_line_string_list);
13349 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13350 ASET (vector, 4, mode_line_string_face);
13351 ASET (vector, 5, mode_line_string_face_prop);
13352
13353 if (obuf)
13354 XSETBUFFER (tmp, obuf);
13355 else
13356 tmp = Qnil;
13357 ASET (vector, 6, tmp);
13358 ASET (vector, 7, owin);
13359 if (target_frame)
13360 {
13361 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13362 struct buffer *b = XBUFFER (buffer);
13363 struct buffer *cb = current_buffer;
13364
13365
13366
13367
13368 ASET (vector, 8, target_frame->selected_window);
13369 if (FRAME_TERMCAP_P (target_frame))
13370 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13371
13372
13373
13374
13375 ASET (vector, 10, buffer);
13376 current_buffer = b;
13377 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13378 current_buffer = cb;
13379 }
13380
13381 return vector;
13382 }
13383
13384 static void
13385 unwind_format_mode_line (Lisp_Object vector)
13386 {
13387 Lisp_Object old_window = AREF (vector, 7);
13388 Lisp_Object target_frame_window = AREF (vector, 8);
13389 Lisp_Object old_top_frame = AREF (vector, 9);
13390
13391 mode_line_target = XFIXNUM (AREF (vector, 0));
13392 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13393 mode_line_string_list = AREF (vector, 2);
13394 if (! EQ (AREF (vector, 3), Qt))
13395 mode_line_proptrans_alist = AREF (vector, 3);
13396 mode_line_string_face = AREF (vector, 4);
13397 mode_line_string_face_prop = AREF (vector, 5);
13398
13399
13400 if (WINDOW_LIVE_P (old_window))
13401 {
13402
13403
13404
13405 if (WINDOW_LIVE_P (target_frame_window))
13406 {
13407 Lisp_Object frame
13408 = WINDOW_FRAME (XWINDOW (target_frame_window));
13409
13410 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13411 Fselect_window (target_frame_window, Qt);
13412
13413 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13414
13415
13416 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13417 Fselect_frame (old_top_frame, Qt);
13418 }
13419
13420 Fselect_window (old_window, Qt);
13421
13422
13423
13424
13425 if (WINDOW_LIVE_P (target_frame_window))
13426 {
13427 Lisp_Object buffer = AREF (vector, 10);
13428
13429 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13430 {
13431 struct buffer *cb = current_buffer;
13432
13433 current_buffer = XBUFFER (buffer);
13434 set_point_from_marker (AREF (vector, 11));
13435 ASET (vector, 11, Qnil);
13436 current_buffer = cb;
13437 }
13438 }
13439 }
13440
13441 if (!NILP (AREF (vector, 6)))
13442 {
13443 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13444 ASET (vector, 6, Qnil);
13445 }
13446
13447 Vmode_line_unwind_vector = vector;
13448 }
13449
13450
13451
13452
13453
13454 static void
13455 store_mode_line_noprop_char (char c)
13456 {
13457
13458
13459 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13460 {
13461 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13462 ptrdiff_t size = len;
13463 mode_line_noprop_buf =
13464 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13465 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13466 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13467 }
13468
13469 *mode_line_noprop_ptr++ = c;
13470 }
13471
13472
13473
13474
13475
13476
13477
13478
13479
13480
13481 static int
13482 store_mode_line_noprop (const char *string, int field_width, int precision)
13483 {
13484 const unsigned char *str = (const unsigned char *) string;
13485 int n = 0;
13486 ptrdiff_t dummy, nbytes;
13487
13488
13489 nbytes = strlen (string);
13490 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13491 while (nbytes--)
13492 store_mode_line_noprop_char (*str++);
13493
13494
13495 while (field_width > 0
13496 && n < field_width)
13497 {
13498 store_mode_line_noprop_char (' ');
13499 ++n;
13500 }
13501
13502 return n;
13503 }
13504
13505
13506
13507
13508
13509 #ifdef HAVE_WINDOW_SYSTEM
13510
13511
13512
13513
13514
13515 void
13516 gui_consider_frame_title (Lisp_Object frame)
13517 {
13518 struct frame *f = XFRAME (frame);
13519 Lisp_Object format_data;
13520
13521 if ((FRAME_WINDOW_P (f)
13522 || FRAME_MINIBUF_ONLY_P (f)
13523 || f->explicit_name)
13524 && !FRAME_TOOLTIP_P (f))
13525 {
13526
13527 Lisp_Object tail, other_frame, fmt;
13528 ptrdiff_t title_start;
13529 char *title;
13530 ptrdiff_t len;
13531 struct it it;
13532 specpdl_ref count = SPECPDL_INDEX ();
13533
13534 FOR_EACH_FRAME (tail, other_frame)
13535 {
13536 struct frame *tf = XFRAME (other_frame);
13537
13538 if (tf != f
13539 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13540 && !FRAME_MINIBUF_ONLY_P (tf)
13541 && !FRAME_PARENT_FRAME (tf)
13542 && !FRAME_TOOLTIP_P (tf)
13543 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13544 break;
13545 }
13546
13547
13548 multiple_frames = CONSP (tail);
13549
13550
13551
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561 specbind (Qinhibit_redisplay, Qt);
13562
13563
13564
13565
13566
13567
13568
13569
13570 format_data = format_mode_line_unwind_data (f, current_buffer,
13571 selected_window,
13572 false);
13573 record_unwind_protect (unwind_format_mode_line, format_data);
13574
13575 Fselect_window (f->selected_window, Qt);
13576 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13577 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13578 ? Vicon_title_format : Vframe_title_format);
13579
13580 mode_line_target = MODE_LINE_TITLE;
13581 title_start = MODE_LINE_NOPROP_LEN (0);
13582 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13583 NULL, DEFAULT_FACE_ID);
13584 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13585 len = MODE_LINE_NOPROP_LEN (title_start);
13586 title = mode_line_noprop_buf + title_start;
13587
13588
13589 ptrdiff_t nchars = 0;
13590 len = str_as_multibyte ((unsigned char *) title,
13591 mode_line_noprop_buf_end - title,
13592 len, &nchars);
13593 unbind_to (count, Qnil);
13594
13595
13596
13597
13598
13599
13600 if ((! STRINGP (f->name)
13601 || SBYTES (f->name) != len
13602 || memcmp (title, SDATA (f->name), len) != 0)
13603 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13604 {
13605 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13606 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13607 }
13608 }
13609 }
13610
13611 #endif
13612
13613
13614
13615
13616
13617
13618
13619 #define REDISPLAY_SOME_P() \
13620 ((windows_or_buffers_changed == 0 \
13621 || windows_or_buffers_changed == REDISPLAY_SOME) \
13622 && (update_mode_lines == 0 \
13623 || update_mode_lines == REDISPLAY_SOME))
13624
13625 static bool
13626 needs_no_redisplay (struct window *w)
13627 {
13628 struct buffer *buffer = XBUFFER (w->contents);
13629 struct frame *f = XFRAME (w->frame);
13630 return (REDISPLAY_SOME_P ()
13631 && !w->redisplay
13632 && !w->update_mode_line
13633 && !f->face_change
13634 && !f->redisplay
13635 && !buffer->text->redisplay
13636 && window_point (w) == w->last_point);
13637 }
13638
13639
13640
13641
13642 static void
13643 prepare_menu_bars (void)
13644 {
13645 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13646 bool some_windows = REDISPLAY_SOME_P ();
13647
13648 if (FUNCTIONP (Vpre_redisplay_function))
13649 {
13650 Lisp_Object windows = all_windows ? Qt : Qnil;
13651 if (all_windows && some_windows)
13652 {
13653 Lisp_Object ws = window_list ();
13654 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13655 {
13656 Lisp_Object this = XCAR (ws);
13657 struct window *w = XWINDOW (this);
13658
13659
13660 if (!needs_no_redisplay (w))
13661 windows = Fcons (this, windows);
13662 }
13663 }
13664 safe__call1 (true, Vpre_redisplay_function, windows);
13665 }
13666
13667
13668
13669
13670 #ifdef HAVE_WINDOW_SYSTEM
13671 if (all_windows)
13672 {
13673 Lisp_Object tail, frame;
13674
13675 FOR_EACH_FRAME (tail, frame)
13676 {
13677 struct frame *f = XFRAME (frame);
13678 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13679 if (some_windows
13680 && !f->redisplay
13681 && !w->redisplay
13682 && !XBUFFER (w->contents)->text->redisplay)
13683 continue;
13684
13685 if (!FRAME_TOOLTIP_P (f)
13686 && (FRAME_ICONIFIED_P (f)
13687 || FRAME_VISIBLE_P (f) == 1
13688
13689
13690
13691
13692
13693
13694
13695
13696
13697 || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
13698 gui_consider_frame_title (frame);
13699 }
13700 }
13701 #endif
13702
13703
13704
13705
13706 if (all_windows)
13707 {
13708 Lisp_Object tail, frame;
13709 specpdl_ref count = SPECPDL_INDEX ();
13710
13711
13712 bool menu_bar_hooks_run = false;
13713
13714 record_unwind_save_match_data ();
13715
13716 FOR_EACH_FRAME (tail, frame)
13717 {
13718 struct frame *f = XFRAME (frame);
13719 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13720
13721
13722 if (FRAME_TOOLTIP_P (f))
13723 continue;
13724
13725 if (some_windows
13726 && !f->redisplay
13727 && !w->redisplay
13728 && !XBUFFER (w->contents)->text->redisplay)
13729 continue;
13730
13731 if (!FRAME_PARENT_FRAME (f))
13732 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13733
13734 update_tab_bar (f, false);
13735 #ifdef HAVE_WINDOW_SYSTEM
13736 update_tool_bar (f, false);
13737 #endif
13738 }
13739
13740 unbind_to (count, Qnil);
13741 }
13742 else
13743 {
13744 struct frame *sf = SELECTED_FRAME ();
13745
13746 if (!FRAME_PARENT_FRAME (sf))
13747 update_menu_bar (sf, true, false);
13748
13749 update_tab_bar (sf, true);
13750 #ifdef HAVE_WINDOW_SYSTEM
13751 update_tool_bar (sf, true);
13752 #endif
13753 }
13754 }
13755
13756
13757
13758
13759
13760
13761
13762
13763
13764
13765
13766
13767
13768 static bool
13769 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13770 {
13771 Lisp_Object window;
13772 struct window *w;
13773
13774
13775
13776
13777 if (inhibit_menubar_update)
13778 return hooks_run;
13779
13780 window = FRAME_SELECTED_WINDOW (f);
13781 w = XWINDOW (window);
13782
13783 if (FRAME_WINDOW_P (f)
13784 ?
13785 #ifdef HAVE_EXT_MENU_BAR
13786 FRAME_EXTERNAL_MENU_BAR (f)
13787 #else
13788 FRAME_MENU_BAR_LINES (f) > 0
13789 #endif
13790 : FRAME_MENU_BAR_LINES (f) > 0)
13791 {
13792
13793
13794
13795
13796
13797
13798
13799 if (windows_or_buffers_changed
13800
13801
13802 || update_mode_lines
13803 || window_buffer_changed (w))
13804 {
13805 struct buffer *prev = current_buffer;
13806 specpdl_ref count = SPECPDL_INDEX ();
13807
13808 specbind (Qinhibit_menubar_update, Qt);
13809
13810 set_buffer_internal_1 (XBUFFER (w->contents));
13811 if (save_match_data)
13812 record_unwind_save_match_data ();
13813 if (NILP (Voverriding_local_map_menu_flag))
13814 {
13815 specbind (Qoverriding_terminal_local_map, Qnil);
13816 specbind (Qoverriding_local_map, Qnil);
13817 }
13818
13819 if (!hooks_run)
13820 {
13821
13822 safe_run_hooks (Qactivate_menubar_hook);
13823
13824
13825
13826 safe_run_hooks (Qmenu_bar_update_hook);
13827
13828 hooks_run = true;
13829 }
13830
13831 XSETFRAME (Vmenu_updating_frame, f);
13832 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13833
13834
13835 #ifdef HAVE_EXT_MENU_BAR
13836 if (FRAME_WINDOW_P (f))
13837 {
13838 #if defined (HAVE_NS)
13839
13840
13841 if (f == SELECTED_FRAME ())
13842 #endif
13843 set_frame_menubar (f, false);
13844 }
13845 else
13846
13847
13848 w->update_mode_line = true;
13849 #else
13850
13851
13852 w->update_mode_line = true;
13853 #endif
13854
13855 unbind_to (count, Qnil);
13856 set_buffer_internal_1 (prev);
13857 }
13858 }
13859
13860 return hooks_run;
13861 }
13862
13863
13864
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874 static void
13875 restore_selected_window (Lisp_Object window)
13876 {
13877 if (WINDOW_LIVE_P (window))
13878
13879
13880 {
13881 selected_window = window;
13882 selected_frame = XWINDOW (window)->frame;
13883 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13884 }
13885 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13886
13887
13888 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13889 else
13890
13891
13892
13893 {
13894 Lisp_Object tail;
13895 Lisp_Object frame UNINIT;
13896
13897 FOR_EACH_FRAME (tail, frame)
13898 {
13899 struct frame *f = XFRAME (frame);
13900
13901 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13902 {
13903 selected_frame = frame;
13904 selected_window = FRAME_SELECTED_WINDOW (f);
13905
13906 return;
13907 }
13908 }
13909
13910
13911 emacs_abort ();
13912 }
13913 }
13914
13915
13916 static void
13917 restore_frame_selected_window (Lisp_Object window)
13918 {
13919 if (WINDOW_LIVE_P (window))
13920
13921
13922
13923 {
13924 Lisp_Object frame = XWINDOW (window)->frame;
13925
13926 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13927 if (EQ (frame, selected_frame))
13928 selected_window = window;
13929 }
13930 }
13931
13932
13933
13934
13935
13936
13937 static void
13938 update_tab_bar (struct frame *f, bool save_match_data)
13939 {
13940 bool do_update = false;
13941
13942 #ifdef HAVE_WINDOW_SYSTEM
13943 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
13944 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
13945 do_update = true;
13946 }
13947 else
13948 #endif
13949 if (FRAME_TAB_BAR_LINES (f) > 0)
13950 do_update = true;
13951
13952 if (do_update)
13953 {
13954 Lisp_Object window;
13955 struct window *w;
13956
13957 window = FRAME_SELECTED_WINDOW (f);
13958 w = XWINDOW (window);
13959
13960
13961
13962
13963
13964
13965
13966
13967 if (windows_or_buffers_changed
13968 || w->update_mode_line
13969 || update_mode_lines
13970 || window_buffer_changed (w))
13971 {
13972 struct buffer *prev = current_buffer;
13973 specpdl_ref count = SPECPDL_INDEX ();
13974 Lisp_Object new_tab_bar;
13975 int new_n_tab_bar;
13976
13977
13978
13979
13980 set_buffer_internal_1 (XBUFFER (w->contents));
13981
13982
13983 if (save_match_data)
13984 record_unwind_save_match_data ();
13985
13986
13987 if (NILP (Voverriding_local_map_menu_flag))
13988 {
13989 specbind (Qoverriding_terminal_local_map, Qnil);
13990 specbind (Qoverriding_local_map, Qnil);
13991 }
13992
13993
13994
13995
13996
13997 eassert (EQ (selected_window,
13998
13999
14000 XFRAME (selected_frame)->selected_window));
14001 #ifdef HAVE_WINDOW_SYSTEM
14002 Lisp_Object frame;
14003 record_unwind_protect (restore_selected_window, selected_window);
14004 XSETFRAME (frame, f);
14005 selected_frame = frame;
14006 selected_window = FRAME_SELECTED_WINDOW (f);
14007 #endif
14008
14009
14010 new_tab_bar
14011 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
14012 &new_n_tab_bar);
14013
14014
14015 if (new_n_tab_bar != f->n_tab_bar_items
14016 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14017 {
14018
14019
14020
14021 block_input ();
14022 fset_tab_bar_items (f, new_tab_bar);
14023 f->n_tab_bar_items = new_n_tab_bar;
14024 w->update_mode_line = true;
14025 unblock_input ();
14026 }
14027
14028 unbind_to (count, Qnil);
14029 set_buffer_internal_1 (prev);
14030 }
14031 }
14032 }
14033
14034
14035
14036
14037
14038
14039
14040
14041
14042
14043
14044 static void
14045 display_tab_bar (struct window *w)
14046 {
14047 struct frame *f = XFRAME (WINDOW_FRAME (w));
14048 struct it it;
14049 Lisp_Object items;
14050 int i;
14051
14052
14053 #ifdef HAVE_NTGUI
14054 if (FRAME_W32_P (f))
14055 return;
14056 #endif
14057 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14058 if (FRAME_X_P (f))
14059 return;
14060 #endif
14061
14062 #ifdef HAVE_NS
14063 if (FRAME_NS_P (f))
14064 return;
14065 #endif
14066
14067 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14068 eassert (!FRAME_WINDOW_P (f));
14069 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14070 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14071 TAB_BAR_FACE_ID);
14072 it.first_visible_x = 0;
14073 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14074 #elif defined (HAVE_X_WINDOWS)
14075 if (FRAME_WINDOW_P (f))
14076 {
14077
14078
14079 struct window *tab_w;
14080 tab_w = XWINDOW (f->tab_bar_window);
14081 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14082 TAB_BAR_FACE_ID);
14083 it.first_visible_x = 0;
14084 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14085 }
14086 else
14087 #endif
14088 {
14089
14090
14091 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14092 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14093 TAB_BAR_FACE_ID);
14094 it.first_visible_x = 0;
14095 it.last_visible_x = FRAME_COLS (f);
14096 }
14097
14098
14099
14100
14101 it.paragraph_embedding = L2R;
14102
14103
14104 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14105 {
14106 struct glyph_row *row = it.glyph_row + i;
14107 clear_glyph_row (row);
14108 row->enabled_p = true;
14109 row->full_width_p = true;
14110 row->reversed_p = false;
14111 }
14112
14113
14114 items = it.f->tab_bar_items;
14115 int j;
14116 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14117 {
14118 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14119
14120
14121 if (NILP (string))
14122 break;
14123
14124 if (it.current_x < it.last_visible_x)
14125 display_string (NULL, string, Qnil, 0, 0, &it,
14126 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14127 }
14128
14129
14130 if (it.current_x < it.last_visible_x)
14131 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14132
14133
14134 compute_line_metrics (&it);
14135 }
14136
14137 #ifdef HAVE_WINDOW_SYSTEM
14138
14139
14140
14141
14142
14143 static void
14144 build_desired_tab_bar_string (struct frame *f)
14145 {
14146 int i;
14147 Lisp_Object caption;
14148
14149 caption = Qnil;
14150
14151
14152 fset_desired_tab_bar_string (f, build_string (""));
14153
14154
14155
14156
14157 for (i = 0; i < f->n_tab_bar_items; ++i)
14158 {
14159 #define PROP(IDX) \
14160 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14161
14162 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14163
14164
14165
14166
14167
14168 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14169
14170 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14171 props, caption);
14172
14173 f->desired_tab_bar_string =
14174 concat2 (f->desired_tab_bar_string, caption);
14175
14176 #undef PROP
14177 }
14178 }
14179
14180
14181
14182
14183
14184
14185
14186
14187
14188
14189
14190
14191
14192
14193 static void
14194 display_tab_bar_line (struct it *it, int height)
14195 {
14196 struct glyph_row *row = it->glyph_row;
14197 int max_x = it->last_visible_x;
14198 struct glyph *last;
14199
14200
14201 clear_glyph_row (row);
14202 row->enabled_p = true;
14203 row->y = it->current_y;
14204
14205
14206
14207 it->start_of_box_run_p = true;
14208
14209 bool enough = false;
14210 while (it->current_x < max_x)
14211 {
14212 int x, n_glyphs_before, i, nglyphs;
14213 struct it it_before;
14214
14215
14216 if (!get_next_display_element (it))
14217 {
14218
14219 if (height < 0 && !it->hpos)
14220 return;
14221 break;
14222 }
14223
14224
14225 n_glyphs_before = row->used[TEXT_AREA];
14226 it_before = *it;
14227
14228 PRODUCE_GLYPHS (it);
14229
14230 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14231 i = 0;
14232 x = it_before.current_x;
14233 while (i < nglyphs)
14234 {
14235 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14236
14237 if (x + glyph->pixel_width > max_x)
14238 {
14239
14240 row->used[TEXT_AREA] = n_glyphs_before;
14241 *it = it_before;
14242
14243
14244
14245 if (n_glyphs_before == 0
14246 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14247 break;
14248 goto out;
14249 }
14250
14251 ++it->hpos;
14252 x += glyph->pixel_width;
14253 ++i;
14254 }
14255
14256 enough = ITERATOR_AT_END_OF_LINE_P (it);
14257 set_iterator_to_next (it, true);
14258
14259
14260 if (enough)
14261 break;
14262 }
14263
14264 out:;
14265
14266 row->displays_text_p = row->used[TEXT_AREA] != 0;
14267
14268
14269
14270
14271
14272
14273
14274 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14275 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14276 it->face_id = DEFAULT_FACE_ID;
14277
14278 extend_face_to_end_of_line (it);
14279 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14280 last->right_box_line_p = true;
14281 if (last == row->glyphs[TEXT_AREA])
14282 last->left_box_line_p = true;
14283
14284
14285 if ((height -= it->max_ascent + it->max_descent) > 0)
14286 {
14287
14288 height %= FRAME_LINE_HEIGHT (it->f);
14289 it->max_ascent += height / 2;
14290 it->max_descent += (height + 1) / 2;
14291 }
14292
14293 compute_line_metrics (it);
14294
14295
14296 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14297 {
14298 row->height = row->phys_height = it->last_visible_y - row->y;
14299 row->visible_height = row->height;
14300 row->ascent = row->phys_ascent = 0;
14301 row->extra_line_spacing = 0;
14302 }
14303
14304 row->full_width_p = true;
14305 row->continued_p = false;
14306 row->truncated_on_left_p = false;
14307 row->truncated_on_right_p = false;
14308
14309 it->current_x = it->hpos = 0;
14310 it->current_y += row->height;
14311 ++it->vpos;
14312 ++it->glyph_row;
14313 }
14314
14315
14316
14317
14318
14319 static int
14320 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14321 {
14322 struct window *w = XWINDOW (f->tab_bar_window);
14323 struct it it;
14324
14325
14326
14327 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14328
14329
14330
14331 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14332 temp_row->reversed_p = false;
14333 it.first_visible_x = 0;
14334 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14335 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14336 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14337 it.paragraph_embedding = L2R;
14338
14339 clear_glyph_row (temp_row);
14340 while (!ITERATOR_AT_END_P (&it))
14341 {
14342 it.glyph_row = temp_row;
14343 display_tab_bar_line (&it, -1);
14344 }
14345 clear_glyph_row (temp_row);
14346
14347
14348 if (n_rows)
14349 *n_rows = it.vpos > 0 ? it.vpos : -1;
14350
14351 if (pixelwise)
14352 return it.current_y;
14353 else
14354 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14355 }
14356
14357 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14358 0, 2, 0,
14359 doc:
14360
14361 )
14362 (Lisp_Object frame, Lisp_Object pixelwise)
14363 {
14364 int height = 0;
14365
14366 struct frame *f = decode_any_frame (frame);
14367
14368 if (WINDOWP (f->tab_bar_window)
14369 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14370 {
14371 update_tab_bar (f, true);
14372 if (f->n_tab_bar_items)
14373 {
14374 build_desired_tab_bar_string (f);
14375 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14376 }
14377 }
14378
14379 return make_fixnum (height);
14380 }
14381
14382
14383
14384
14385 static bool
14386 redisplay_tab_bar (struct frame *f)
14387 {
14388 struct window *w;
14389 struct it it;
14390 struct glyph_row *row;
14391
14392 f->tab_bar_redisplayed = true;
14393
14394
14395
14396
14397
14398 if (!WINDOWP (f->tab_bar_window)
14399 || (w = XWINDOW (f->tab_bar_window),
14400 WINDOW_TOTAL_LINES (w) == 0))
14401 {
14402
14403
14404
14405
14406
14407 f->tab_bar_resized = true;
14408
14409 return false;
14410 }
14411
14412
14413 build_desired_tab_bar_string (f);
14414
14415 int new_nrows;
14416 int new_height = tab_bar_height (f, &new_nrows, true);
14417
14418 if (f->n_tab_bar_rows == 0)
14419 {
14420 f->n_tab_bar_rows = new_nrows;
14421 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14422 frame_default_tab_bar_height = new_height;
14423 }
14424
14425
14426
14427 if (new_nrows > f->n_tab_bar_rows
14428 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14429 && !f->minimize_tab_bar_window_p
14430 && new_height > WINDOW_PIXEL_HEIGHT (w))
14431 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14432 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14433 {
14434 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14435 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14436 if (new_nrows != f->n_tab_bar_rows)
14437 f->n_tab_bar_rows = new_nrows;
14438 clear_glyph_matrix (w->desired_matrix);
14439 f->fonts_changed = true;
14440 return true;
14441 }
14442
14443
14444 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14445 it.first_visible_x = 0;
14446 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14447 row = it.glyph_row;
14448 row->reversed_p = false;
14449 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14450 STRING_MULTIBYTE (f->desired_tab_bar_string));
14451
14452
14453
14454
14455
14456
14457
14458 it.paragraph_embedding = L2R;
14459
14460
14461
14462 if (f->n_tab_bar_rows > 0)
14463 {
14464 int border, rows, height, extra;
14465
14466 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14467 border = XFIXNUM (Vtab_bar_border);
14468 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14469 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14470 else if (EQ (Vtab_bar_border, Qborder_width))
14471 border = f->border_width;
14472 else
14473 border = 0;
14474 if (border < 0)
14475 border = 0;
14476
14477 rows = f->n_tab_bar_rows;
14478 height = max (1, (it.last_visible_y - border) / rows);
14479 extra = it.last_visible_y - border - height * rows;
14480
14481 while (it.current_y < it.last_visible_y)
14482 {
14483 int h = 0;
14484 if (extra > 0 && rows-- > 0)
14485 {
14486 h = (extra + rows - 1) / rows;
14487 extra -= h;
14488 }
14489 display_tab_bar_line (&it, height + h);
14490 }
14491 }
14492 else
14493 {
14494 while (it.current_y < it.last_visible_y)
14495 display_tab_bar_line (&it, 0);
14496 }
14497
14498
14499
14500 w->desired_matrix->no_scrolling_p = true;
14501 w->must_be_updated_p = true;
14502
14503 if (!NILP (Vauto_resize_tab_bars))
14504 {
14505 bool change_height_p = false;
14506
14507
14508
14509 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14510 change_height_p = true;
14511
14512
14513
14514
14515
14516 row = it.glyph_row - 1;
14517
14518
14519
14520
14521 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14522 && row->height >= FRAME_LINE_HEIGHT (f))
14523 change_height_p = true;
14524
14525
14526
14527 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14528 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14529 change_height_p = true;
14530
14531
14532
14533 if (change_height_p)
14534 {
14535 int nrows;
14536 int new_height = tab_bar_height (f, &nrows, true);
14537
14538 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14539 && !f->minimize_tab_bar_window_p)
14540 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14541 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14542 f->minimize_tab_bar_window_p = false;
14543
14544 if (change_height_p)
14545 {
14546 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14547 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14548 frame_default_tab_bar_height = new_height;
14549 clear_glyph_matrix (w->desired_matrix);
14550 f->n_tab_bar_rows = nrows;
14551 f->fonts_changed = true;
14552
14553 return true;
14554 }
14555 }
14556 }
14557
14558 f->minimize_tab_bar_window_p = false;
14559 return false;
14560 }
14561
14562
14563
14564
14565
14566
14567
14568 static bool
14569 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14570 int *prop_idx, bool *close_p)
14571 {
14572 Lisp_Object prop;
14573 ptrdiff_t charpos;
14574
14575
14576
14577
14578 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14579 charpos = max (0, charpos);
14580
14581
14582
14583
14584 prop = Fget_text_property (make_fixnum (charpos),
14585 Qmenu_item, f->current_tab_bar_string);
14586 if (! FIXNUMP (prop))
14587 return false;
14588 *prop_idx = XFIXNUM (prop);
14589
14590 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14591 Qclose_tab,
14592 f->current_tab_bar_string));
14593
14594 return true;
14595 }
14596
14597
14598
14599
14600
14601
14602
14603
14604
14605
14606
14607
14608 static int
14609 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14610 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14611 {
14612 struct window *w = XWINDOW (f->tab_bar_window);
14613 int area;
14614
14615
14616 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14617 if (*glyph == NULL)
14618 return -1;
14619
14620
14621
14622 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14623 return -1;
14624
14625 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14626 }
14627
14628
14629
14630
14631
14632
14633
14634
14635 Lisp_Object
14636 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14637 int modifiers)
14638 {
14639 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14640 struct window *w = XWINDOW (f->tab_bar_window);
14641 int hpos, vpos, prop_idx;
14642 bool close_p;
14643 struct glyph *glyph;
14644 Lisp_Object enabled_p;
14645 int ts;
14646
14647 frame_to_window_pixel_xy (w, &x, &y);
14648 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14649 if (ts == -1)
14650 return Fcons (Qtab_bar, Qnil);
14651
14652
14653 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14654 if (NILP (enabled_p))
14655 return Qnil;
14656
14657 if (down_p)
14658 {
14659
14660 if (!NILP (Vmouse_highlight))
14661 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14662 f->last_tab_bar_item = prop_idx;
14663 }
14664 else
14665 {
14666
14667 if (!NILP (Vmouse_highlight))
14668 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14669 f->last_tab_bar_item = -1;
14670 }
14671
14672 Lisp_Object caption =
14673 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14674
14675 AUTO_LIST2 (props, Qmenu_item,
14676 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14677 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14678 close_p ? Qt : Qnil));
14679
14680 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14681 props, caption);
14682
14683 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14684 }
14685
14686
14687
14688
14689
14690
14691 static void
14692 note_tab_bar_highlight (struct frame *f, int x, int y)
14693 {
14694 Lisp_Object window = f->tab_bar_window;
14695 struct window *w = XWINDOW (window);
14696 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14697 int hpos, vpos;
14698 struct glyph *glyph;
14699 struct glyph_row *row;
14700 int i;
14701 Lisp_Object enabled_p;
14702 int prop_idx;
14703 bool close_p;
14704 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14705 int rc;
14706
14707
14708
14709 if (x <= 0 || y <= 0)
14710 {
14711 clear_mouse_face (hlinfo);
14712 return;
14713 }
14714
14715 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14716 if (rc < 0)
14717 {
14718
14719 clear_mouse_face (hlinfo);
14720 return;
14721 }
14722 else if (rc == 0)
14723
14724 goto set_help_echo;
14725
14726 clear_mouse_face (hlinfo);
14727
14728 bool mouse_down_p = false;
14729
14730
14731
14732
14733
14734 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14735 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14736 && f == dpyinfo->last_mouse_frame);
14737
14738 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14739 && f->last_tab_bar_item != -1)
14740 return;
14741 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14742
14743
14744 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14745 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14746 {
14747
14748
14749 row = MATRIX_ROW (w->current_matrix, vpos);
14750 for (i = x = 0; i < hpos; ++i)
14751 x += row->glyphs[TEXT_AREA][i].pixel_width;
14752
14753
14754 hlinfo->mouse_face_beg_col = hpos;
14755 hlinfo->mouse_face_beg_row = vpos;
14756 hlinfo->mouse_face_beg_x = x;
14757 hlinfo->mouse_face_past_end = false;
14758
14759 hlinfo->mouse_face_end_col = hpos + 1;
14760 hlinfo->mouse_face_end_row = vpos;
14761 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14762 hlinfo->mouse_face_window = window;
14763 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14764
14765
14766 show_mouse_face (hlinfo, draw);
14767 }
14768
14769 set_help_echo:
14770
14771
14772
14773 help_echo_object = help_echo_window = Qnil;
14774 help_echo_pos = -1;
14775 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14776 if (NILP (help_echo_string))
14777 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14778 }
14779
14780 #endif
14781
14782
14783 static Lisp_Object
14784 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14785 {
14786 ptrdiff_t clen = 0;
14787
14788 for (int i = 0; i < f->n_tab_bar_items; i++)
14789 {
14790 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14791 + TAB_BAR_ITEM_CAPTION));
14792 if (NILP (caption))
14793 return Qnil;
14794 clen += SCHARS (caption);
14795 if (x < clen)
14796 {
14797 *prop_idx = i;
14798 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14799 - (clen - x)),
14800 Qclose_tab,
14801 caption));
14802 return caption;
14803 }
14804 }
14805 return Qnil;
14806 }
14807
14808
14809
14810
14811
14812
14813 Lisp_Object
14814 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14815 struct input_event *event)
14816 {
14817
14818 if (y < FRAME_MENU_BAR_LINES (f)
14819 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14820 return Qnil;
14821
14822
14823 int prop_idx;
14824 bool close_p;
14825 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14826
14827 if (NILP (caption))
14828 return Qnil;
14829
14830 if (NILP (AREF (f->tab_bar_items,
14831 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14832 return Qnil;
14833
14834 if (down_p)
14835 f->last_tab_bar_item = prop_idx;
14836 else
14837 f->last_tab_bar_item = -1;
14838
14839 caption = Fcopy_sequence (caption);
14840
14841 AUTO_LIST2 (props, Qmenu_item,
14842 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14843 + TAB_BAR_ITEM_KEY),
14844 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14845 + TAB_BAR_ITEM_BINDING),
14846 close_p ? Qt : Qnil));
14847
14848 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14849 props, caption);
14850
14851 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14852 }
14853
14854
14855
14856
14857
14858
14859
14860 #ifdef HAVE_WINDOW_SYSTEM
14861
14862
14863
14864
14865
14866
14867 static void
14868 update_tool_bar (struct frame *f, bool save_match_data)
14869 {
14870 #ifdef HAVE_EXT_TOOL_BAR
14871 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14872 #else
14873 bool do_update = (WINDOWP (f->tool_bar_window)
14874 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14875 #endif
14876
14877 if (do_update)
14878 {
14879 Lisp_Object window;
14880 struct window *w;
14881
14882 window = FRAME_SELECTED_WINDOW (f);
14883 w = XWINDOW (window);
14884
14885
14886
14887
14888
14889
14890
14891
14892 if (windows_or_buffers_changed
14893 || w->update_mode_line
14894 || update_mode_lines
14895 || window_buffer_changed (w))
14896 {
14897 struct buffer *prev = current_buffer;
14898 specpdl_ref count = SPECPDL_INDEX ();
14899 Lisp_Object frame, new_tool_bar;
14900 int new_n_tool_bar;
14901
14902
14903
14904
14905 set_buffer_internal_1 (XBUFFER (w->contents));
14906
14907
14908 if (save_match_data)
14909 record_unwind_save_match_data ();
14910
14911
14912 if (NILP (Voverriding_local_map_menu_flag))
14913 {
14914 specbind (Qoverriding_terminal_local_map, Qnil);
14915 specbind (Qoverriding_local_map, Qnil);
14916 }
14917
14918
14919
14920
14921
14922 eassert (EQ (selected_window,
14923
14924
14925 XFRAME (selected_frame)->selected_window));
14926 record_unwind_protect (restore_selected_window, selected_window);
14927 XSETFRAME (frame, f);
14928 selected_frame = frame;
14929 selected_window = FRAME_SELECTED_WINDOW (f);
14930
14931
14932 new_tool_bar
14933 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
14934 &new_n_tool_bar);
14935
14936
14937 if (new_n_tool_bar != f->n_tool_bar_items
14938 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
14939 {
14940
14941
14942
14943 block_input ();
14944 fset_tool_bar_items (f, new_tool_bar);
14945 f->n_tool_bar_items = new_n_tool_bar;
14946 w->update_mode_line = true;
14947 unblock_input ();
14948 }
14949
14950 unbind_to (count, Qnil);
14951 set_buffer_internal_1 (prev);
14952 }
14953 }
14954 }
14955
14956 #ifndef HAVE_EXT_TOOL_BAR
14957
14958
14959
14960
14961
14962 static void
14963 build_desired_tool_bar_string (struct frame *f)
14964 {
14965 int i, size, size_needed;
14966 Lisp_Object image, plist;
14967
14968 image = plist = Qnil;
14969
14970
14971
14972
14973
14974 size = (STRINGP (f->desired_tool_bar_string)
14975 ? SCHARS (f->desired_tool_bar_string)
14976 : 0);
14977
14978
14979 size_needed = f->n_tool_bar_items;
14980
14981
14982 if (size < size_needed || NILP (f->desired_tool_bar_string))
14983 fset_desired_tool_bar_string
14984 (f, Fmake_string (make_fixnum (size_needed), make_fixnum (' '), Qnil));
14985 else
14986 {
14987 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
14988 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
14989 props, f->desired_tool_bar_string);
14990 }
14991
14992
14993
14994
14995 for (i = 0; i < f->n_tool_bar_items; ++i)
14996 {
14997 #define PROP(IDX) \
14998 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
14999
15000 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
15001 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
15002 int hmargin, vmargin, relief, idx, end;
15003
15004
15005
15006 image = PROP (TOOL_BAR_ITEM_IMAGES);
15007 if (VECTORP (image))
15008 {
15009 if (enabled_p)
15010 idx = (selected_p
15011 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
15012 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
15013 else
15014 idx = (selected_p
15015 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15016 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15017
15018 eassert (ASIZE (image) >= idx);
15019 image = AREF (image, idx);
15020 }
15021 else
15022 idx = -1;
15023
15024
15025 if (!valid_image_p (image))
15026 continue;
15027
15028
15029 plist = Fcopy_sequence (XCDR (image));
15030
15031
15032 relief = (tool_bar_button_relief >= 0
15033 ? min (tool_bar_button_relief,
15034 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15035 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15036 hmargin = vmargin = relief;
15037
15038 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15039 INT_MAX - max (hmargin, vmargin)))
15040 {
15041 hmargin += XFIXNAT (Vtool_bar_button_margin);
15042 vmargin += XFIXNAT (Vtool_bar_button_margin);
15043 }
15044 else if (CONSP (Vtool_bar_button_margin))
15045 {
15046 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15047 INT_MAX - hmargin))
15048 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15049
15050 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15051 INT_MAX - vmargin))
15052 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15053 }
15054
15055 if (auto_raise_tool_bar_buttons_p)
15056 {
15057
15058
15059 if (selected_p)
15060 {
15061 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15062 hmargin -= relief;
15063 vmargin -= relief;
15064 }
15065 }
15066 else
15067 {
15068
15069
15070
15071 plist = plist_put (plist, QCrelief,
15072 (selected_p
15073 ? make_fixnum (-relief)
15074 : make_fixnum (relief)));
15075 hmargin -= relief;
15076 vmargin -= relief;
15077 }
15078
15079
15080 if (hmargin || vmargin)
15081 {
15082 if (hmargin == vmargin)
15083 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15084 else
15085 plist = plist_put (plist, QCmargin,
15086 Fcons (make_fixnum (hmargin),
15087 make_fixnum (vmargin)));
15088 }
15089
15090
15091
15092
15093 if (!enabled_p && idx < 0)
15094 plist = plist_put (plist, QCconversion, Qdisabled);
15095
15096
15097
15098
15099
15100 image = Fcons (Qimage, plist);
15101 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15102 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15103
15104
15105
15106
15107 if (i + 1 == f->n_tool_bar_items)
15108 end = SCHARS (f->desired_tool_bar_string);
15109 else
15110 end = i + 1;
15111 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15112 props, f->desired_tool_bar_string);
15113 #undef PROP
15114 }
15115 }
15116
15117
15118
15119
15120
15121
15122
15123
15124
15125
15126
15127
15128
15129
15130 static void
15131 display_tool_bar_line (struct it *it, int height)
15132 {
15133 struct glyph_row *row = it->glyph_row;
15134 int max_x = it->last_visible_x;
15135 struct glyph *last;
15136
15137
15138 clear_glyph_row (row);
15139 row->enabled_p = true;
15140 row->y = it->current_y;
15141
15142
15143
15144 it->start_of_box_run_p = true;
15145
15146 while (it->current_x < max_x)
15147 {
15148 int x, n_glyphs_before, i, nglyphs;
15149 struct it it_before;
15150
15151
15152 if (!get_next_display_element (it))
15153 {
15154
15155 if (height < 0 && !it->hpos)
15156 return;
15157 break;
15158 }
15159
15160
15161 n_glyphs_before = row->used[TEXT_AREA];
15162 it_before = *it;
15163
15164 PRODUCE_GLYPHS (it);
15165
15166 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15167 i = 0;
15168 x = it_before.current_x;
15169 while (i < nglyphs)
15170 {
15171 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15172
15173 if (x + glyph->pixel_width > max_x)
15174 {
15175
15176 row->used[TEXT_AREA] = n_glyphs_before;
15177 *it = it_before;
15178
15179
15180
15181 if (n_glyphs_before == 0
15182 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15183 break;
15184 goto out;
15185 }
15186
15187 ++it->hpos;
15188 x += glyph->pixel_width;
15189 ++i;
15190 }
15191
15192
15193 if (ITERATOR_AT_END_OF_LINE_P (it))
15194 break;
15195
15196 set_iterator_to_next (it, true);
15197 }
15198
15199 out:;
15200
15201 row->displays_text_p = row->used[TEXT_AREA] != 0;
15202
15203
15204
15205
15206
15207
15208
15209 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15210 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15211 it->face_id = DEFAULT_FACE_ID;
15212
15213 extend_face_to_end_of_line (it);
15214 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15215 last->right_box_line_p = true;
15216 if (last == row->glyphs[TEXT_AREA])
15217 last->left_box_line_p = true;
15218
15219
15220 if ((height -= it->max_ascent + it->max_descent) > 0)
15221 {
15222
15223 height %= FRAME_LINE_HEIGHT (it->f);
15224 it->max_ascent += height / 2;
15225 it->max_descent += (height + 1) / 2;
15226 }
15227
15228 compute_line_metrics (it);
15229
15230
15231 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15232 {
15233 row->height = row->phys_height = it->last_visible_y - row->y;
15234 row->visible_height = row->height;
15235 row->ascent = row->phys_ascent = 0;
15236 row->extra_line_spacing = 0;
15237 }
15238
15239 row->full_width_p = true;
15240 row->continued_p = false;
15241 row->truncated_on_left_p = false;
15242 row->truncated_on_right_p = false;
15243
15244 it->current_x = it->hpos = 0;
15245 it->current_y += row->height;
15246 ++it->vpos;
15247 ++it->glyph_row;
15248 }
15249
15250
15251
15252
15253
15254 static int
15255 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15256 {
15257 struct window *w = XWINDOW (f->tool_bar_window);
15258 struct it it;
15259
15260
15261
15262 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15263
15264
15265
15266 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15267 temp_row->reversed_p = false;
15268 it.first_visible_x = 0;
15269 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15270 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15271 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15272 it.paragraph_embedding = L2R;
15273
15274 while (!ITERATOR_AT_END_P (&it))
15275 {
15276 clear_glyph_row (temp_row);
15277 it.glyph_row = temp_row;
15278 display_tool_bar_line (&it, -1);
15279 }
15280 clear_glyph_row (temp_row);
15281
15282
15283 if (n_rows)
15284 *n_rows = it.vpos > 0 ? it.vpos : -1;
15285
15286 if (pixelwise)
15287 return it.current_y;
15288 else
15289 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15290 }
15291
15292 #endif
15293
15294 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15295 0, 2, 0,
15296 doc:
15297
15298 )
15299 (Lisp_Object frame, Lisp_Object pixelwise)
15300 {
15301 int height = 0;
15302
15303 #ifndef HAVE_EXT_TOOL_BAR
15304 struct frame *f = decode_any_frame (frame);
15305
15306 if (WINDOWP (f->tool_bar_window)
15307 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15308 {
15309 update_tool_bar (f, true);
15310 if (f->n_tool_bar_items)
15311 {
15312 build_desired_tool_bar_string (f);
15313 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15314 }
15315 }
15316 #endif
15317
15318 return make_fixnum (height);
15319 }
15320
15321 #ifndef HAVE_EXT_TOOL_BAR
15322
15323
15324
15325 static bool
15326 redisplay_tool_bar (struct frame *f)
15327 {
15328 struct window *w;
15329 struct it it;
15330 struct glyph_row *row;
15331
15332 f->tool_bar_redisplayed = true;
15333
15334
15335
15336
15337
15338 if (!WINDOWP (f->tool_bar_window)
15339 || (w = XWINDOW (f->tool_bar_window),
15340 WINDOW_TOTAL_LINES (w) == 0))
15341 {
15342
15343
15344
15345
15346
15347 f->tool_bar_resized = true;
15348
15349 return false;
15350 }
15351
15352
15353 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15354 it.first_visible_x = 0;
15355 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15356 row = it.glyph_row;
15357 row->reversed_p = false;
15358
15359
15360 build_desired_tool_bar_string (f);
15361 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15362 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15363
15364
15365
15366
15367
15368
15369
15370 it.paragraph_embedding = L2R;
15371
15372 if (f->n_tool_bar_rows == 0)
15373 {
15374 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15375
15376 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15377 {
15378 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15379 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15380 frame_default_tool_bar_height = new_height;
15381
15382 clear_glyph_matrix (w->desired_matrix);
15383 f->fonts_changed = true;
15384 return true;
15385 }
15386 }
15387
15388
15389
15390 if (f->n_tool_bar_rows > 0)
15391 {
15392 int border, rows, height, extra;
15393
15394 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15395 border = XFIXNUM (Vtool_bar_border);
15396 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15397 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15398 else if (EQ (Vtool_bar_border, Qborder_width))
15399 border = f->border_width;
15400 else
15401 border = 0;
15402 if (border < 0)
15403 border = 0;
15404
15405 rows = f->n_tool_bar_rows;
15406 height = max (1, (it.last_visible_y - border) / rows);
15407 extra = it.last_visible_y - border - height * rows;
15408
15409 while (it.current_y < it.last_visible_y)
15410 {
15411 int h = 0;
15412 if (extra > 0 && rows-- > 0)
15413 {
15414 h = (extra + rows - 1) / rows;
15415 extra -= h;
15416 }
15417 display_tool_bar_line (&it, height + h);
15418 }
15419 }
15420 else
15421 {
15422 while (it.current_y < it.last_visible_y)
15423 display_tool_bar_line (&it, 0);
15424 }
15425
15426
15427
15428 w->desired_matrix->no_scrolling_p = true;
15429 w->must_be_updated_p = true;
15430
15431 if (!NILP (Vauto_resize_tool_bars))
15432 {
15433 bool change_height_p = false;
15434
15435
15436
15437 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15438 change_height_p = true;
15439
15440
15441
15442
15443
15444 row = it.glyph_row - 1;
15445
15446
15447
15448
15449 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15450 && row->height >= FRAME_LINE_HEIGHT (f))
15451 change_height_p = true;
15452
15453
15454
15455 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15456 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15457 change_height_p = true;
15458
15459
15460
15461 if (change_height_p)
15462 {
15463 int nrows;
15464 int new_height = tool_bar_height (f, &nrows, true);
15465
15466 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15467 && !f->minimize_tool_bar_window_p)
15468 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15469 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15470 f->minimize_tool_bar_window_p = false;
15471
15472 if (change_height_p)
15473 {
15474 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15475 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15476 frame_default_tool_bar_height = new_height;
15477 clear_glyph_matrix (w->desired_matrix);
15478 f->n_tool_bar_rows = nrows;
15479 f->fonts_changed = true;
15480
15481 return true;
15482 }
15483 }
15484 }
15485
15486 f->minimize_tool_bar_window_p = false;
15487
15488 return false;
15489 }
15490
15491
15492
15493
15494
15495
15496 static bool
15497 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15498 {
15499 Lisp_Object prop;
15500 ptrdiff_t charpos;
15501
15502
15503
15504
15505 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15506 charpos = max (0, charpos);
15507
15508
15509
15510
15511 prop = Fget_text_property (make_fixnum (charpos),
15512 Qmenu_item, f->current_tool_bar_string);
15513 if (! FIXNUMP (prop))
15514 return false;
15515 *prop_idx = XFIXNUM (prop);
15516 return true;
15517 }
15518
15519
15520
15521
15522
15523
15524
15525
15526
15527
15528
15529
15530 static int
15531 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15532 int *hpos, int *vpos, int *prop_idx)
15533 {
15534 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15535 struct window *w = XWINDOW (f->tool_bar_window);
15536 int area;
15537
15538
15539 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15540 if (*glyph == NULL)
15541 return -1;
15542
15543
15544
15545 if (!tool_bar_item_info (f, *glyph, prop_idx))
15546 return -1;
15547
15548
15549 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15550 && *vpos >= hlinfo->mouse_face_beg_row
15551 && *vpos <= hlinfo->mouse_face_end_row
15552 && (*vpos > hlinfo->mouse_face_beg_row
15553 || *hpos >= hlinfo->mouse_face_beg_col)
15554 && (*vpos < hlinfo->mouse_face_end_row
15555 || *hpos < hlinfo->mouse_face_end_col
15556 || hlinfo->mouse_face_past_end))
15557 return 0;
15558
15559 return 1;
15560 }
15561
15562
15563
15564
15565
15566
15567
15568
15569 void
15570 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15571 int modifiers, Lisp_Object device)
15572 {
15573 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15574 struct window *w = XWINDOW (f->tool_bar_window);
15575 int hpos, vpos, prop_idx;
15576 struct glyph *glyph;
15577 Lisp_Object enabled_p;
15578 int ts;
15579
15580
15581
15582
15583
15584
15585
15586
15587 frame_to_window_pixel_xy (w, &x, &y);
15588 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15589 if (ts == -1
15590 || (ts != 0 && !NILP (Vmouse_highlight)))
15591 return;
15592
15593
15594
15595
15596 if (NILP (Vmouse_highlight) && !down_p)
15597 prop_idx = f->last_tool_bar_item;
15598
15599
15600 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15601 if (NILP (enabled_p))
15602 return;
15603
15604 if (down_p)
15605 {
15606
15607 if (!NILP (Vmouse_highlight))
15608 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15609 f->last_tool_bar_item = prop_idx;
15610 }
15611 else
15612 {
15613 Lisp_Object key, frame;
15614 struct input_event event;
15615 EVENT_INIT (event);
15616
15617
15618 if (!NILP (Vmouse_highlight))
15619 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15620
15621 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15622
15623 XSETFRAME (frame, f);
15624 event.kind = TOOL_BAR_EVENT;
15625 event.frame_or_window = frame;
15626 event.arg = key;
15627 event.modifiers = modifiers;
15628 event.device = device;
15629 kbd_buffer_store_event (&event);
15630 f->last_tool_bar_item = -1;
15631 }
15632 }
15633
15634 void
15635 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15636 int modifiers)
15637 {
15638 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15639 }
15640
15641
15642
15643
15644
15645 static void
15646 note_tool_bar_highlight (struct frame *f, int x, int y)
15647 {
15648 Lisp_Object window = f->tool_bar_window;
15649 struct window *w = XWINDOW (window);
15650 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15651 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15652 int hpos, vpos;
15653 struct glyph *glyph;
15654 struct glyph_row *row;
15655 int i;
15656 Lisp_Object enabled_p;
15657 int prop_idx;
15658 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15659 bool mouse_down_p;
15660 int rc;
15661
15662
15663
15664 if (x <= 0 || y <= 0)
15665 {
15666 clear_mouse_face (hlinfo);
15667 return;
15668 }
15669
15670 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15671 if (rc < 0)
15672 {
15673
15674 clear_mouse_face (hlinfo);
15675 return;
15676 }
15677 else if (rc == 0)
15678
15679 goto set_help_echo;
15680
15681 clear_mouse_face (hlinfo);
15682
15683
15684 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15685 && f == dpyinfo->last_mouse_frame);
15686
15687 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15688 return;
15689
15690 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15691
15692
15693 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15694 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15695 {
15696
15697
15698 row = MATRIX_ROW (w->current_matrix, vpos);
15699 for (i = x = 0; i < hpos; ++i)
15700 x += row->glyphs[TEXT_AREA][i].pixel_width;
15701
15702
15703 hlinfo->mouse_face_beg_col = hpos;
15704 hlinfo->mouse_face_beg_row = vpos;
15705 hlinfo->mouse_face_beg_x = x;
15706 hlinfo->mouse_face_past_end = false;
15707
15708 hlinfo->mouse_face_end_col = hpos + 1;
15709 hlinfo->mouse_face_end_row = vpos;
15710 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15711 hlinfo->mouse_face_window = window;
15712 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15713
15714
15715 show_mouse_face (hlinfo, draw);
15716 }
15717
15718 set_help_echo:
15719
15720
15721
15722 help_echo_object = help_echo_window = Qnil;
15723 help_echo_pos = -1;
15724 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15725 if (NILP (help_echo_string))
15726 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15727 }
15728
15729 #endif
15730
15731 #endif
15732
15733
15734
15735
15736
15737
15738
15739
15740
15741
15742
15743
15744
15745 static bool
15746 hscroll_window_tree (Lisp_Object window)
15747 {
15748 bool hscrolled_p = false;
15749 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15750 int hscroll_step_abs = 0;
15751 double hscroll_step_rel = 0;
15752
15753 if (hscroll_relative_p)
15754 {
15755 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15756 if (hscroll_step_rel < 0)
15757 {
15758 hscroll_relative_p = false;
15759 hscroll_step_abs = 0;
15760 }
15761 }
15762 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15763 {
15764 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15765 if (hscroll_step_abs < 0)
15766 hscroll_step_abs = 0;
15767 }
15768 else
15769 hscroll_step_abs = 0;
15770
15771 while (WINDOWP (window))
15772 {
15773 struct window *w = XWINDOW (window);
15774
15775 if (WINDOWP (w->contents))
15776 hscrolled_p |= hscroll_window_tree (w->contents);
15777 else if (w->cursor.vpos >= 0
15778
15779
15780
15781
15782
15783
15784 && !(w == XWINDOW (echo_area_window)
15785 && !NILP (echo_area_buffer[0])))
15786 {
15787 int h_margin;
15788 int text_area_width;
15789 struct glyph_row *cursor_row;
15790 struct glyph_row *bottom_row;
15791
15792 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15793 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15794 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15795 else
15796 cursor_row = bottom_row - 1;
15797
15798 if (!cursor_row->enabled_p)
15799 {
15800 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15801 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15802 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15803 else
15804 cursor_row = bottom_row - 1;
15805 }
15806 bool row_r2l_p = cursor_row->reversed_p;
15807 bool hscl = hscrolling_current_line_p (w);
15808 int x_offset = 0;
15809
15810
15811 if (!NILP (Vdisplay_line_numbers))
15812 {
15813 struct glyph *g;
15814 if (!row_r2l_p)
15815 {
15816 for (g = cursor_row->glyphs[TEXT_AREA];
15817 g < cursor_row->glyphs[TEXT_AREA]
15818 + cursor_row->used[TEXT_AREA];
15819 g++)
15820 {
15821 if (!(NILP (g->object) && g->charpos < 0))
15822 break;
15823 x_offset += g->pixel_width;
15824 }
15825 }
15826 else
15827 {
15828 for (g = cursor_row->glyphs[TEXT_AREA]
15829 + cursor_row->used[TEXT_AREA];
15830 g > cursor_row->glyphs[TEXT_AREA];
15831 g--)
15832 {
15833 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
15834 break;
15835 x_offset += (g - 1)->pixel_width;
15836 }
15837 }
15838 }
15839 if (cursor_row->truncated_on_left_p)
15840 {
15841
15842 struct frame *f = XFRAME (WINDOW_FRAME (w));
15843 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
15844 }
15845
15846 text_area_width = window_box_width (w, TEXT_AREA);
15847
15848
15849 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
15850 * WINDOW_FRAME_COLUMN_WIDTH (w));
15851
15852
15853
15854 if (w->suspend_auto_hscroll
15855 && NILP (Fequal (Fwindow_point (window),
15856 Fwindow_old_point (window))))
15857 {
15858 w->suspend_auto_hscroll = false;
15859
15860
15861
15862
15863 if (w->min_hscroll == 0 && w->hscroll > 0
15864 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
15865 Qcurrent_line))
15866 SET_FRAME_GARBAGED (XFRAME (w->frame));
15867 }
15868
15869
15870 Fset_marker (w->old_pointm,
15871 ((w == XWINDOW (selected_window))
15872 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
15873 : Fmarker_position (w->pointm)),
15874 w->contents);
15875
15876 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
15877 && !w->suspend_auto_hscroll
15878
15879
15880
15881
15882
15883
15884 && (CHARPOS (cursor_row->start.pos)
15885 >= BUF_BEG (XBUFFER (w->contents)))
15886
15887
15888
15889
15890 && ((!row_r2l_p
15891 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
15892 || (cursor_row->enabled_p
15893 && cursor_row->truncated_on_right_p
15894 && (w->cursor.x >= text_area_width - h_margin))))
15895
15896
15897
15898
15899
15900
15901 || (row_r2l_p
15902 && ((cursor_row->enabled_p
15903
15904
15905
15906 && cursor_row->truncated_on_right_p
15907 && w->cursor.x <= h_margin)
15908 || (w->hscroll
15909 && (w->cursor.x >= (text_area_width - h_margin
15910 - x_offset)))))
15911
15912
15913
15914
15915
15916 || (hscl
15917 && w->hscroll != w->min_hscroll
15918 && !cursor_row->truncated_on_left_p)))
15919 {
15920 struct it it;
15921 ptrdiff_t hscroll;
15922 struct buffer *saved_current_buffer;
15923 ptrdiff_t pt;
15924 int wanted_x;
15925
15926
15927 saved_current_buffer = current_buffer;
15928 current_buffer = XBUFFER (w->contents);
15929
15930 if (w == XWINDOW (selected_window))
15931 pt = PT;
15932 else
15933 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
15934
15935
15936
15937 init_to_row_start (&it, w, cursor_row);
15938 if (hscl)
15939 it.first_visible_x = window_hscroll_limited (w, it.f)
15940 * FRAME_COLUMN_WIDTH (it.f);
15941 it.last_visible_x = DISP_INFINITY;
15942
15943 ptrdiff_t nchars = pt - IT_CHARPOS (it);
15944 if (current_buffer->long_line_optimizations_p
15945 && nchars > large_hscroll_threshold)
15946 {
15947
15948
15949
15950
15951 fast_move_it_horizontally (&it, nchars);
15952 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
15953 }
15954 else
15955 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
15956
15957
15958
15959
15960
15961
15962 if (it.method == GET_FROM_STRING && pt > 1)
15963 {
15964 init_to_row_start (&it, w, cursor_row);
15965 if (hscl)
15966 it.first_visible_x = (window_hscroll_limited (w, it.f)
15967 * FRAME_COLUMN_WIDTH (it.f));
15968 if (current_buffer->long_line_optimizations_p
15969 && nchars > large_hscroll_threshold)
15970 {
15971 fast_move_it_horizontally (&it, nchars - 1);
15972 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
15973 }
15974 else
15975 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
15976 }
15977 current_buffer = saved_current_buffer;
15978
15979
15980 if (!hscroll_relative_p && hscroll_step_abs == 0)
15981 hscroll = max (0, (it.current_x
15982 - (ITERATOR_AT_END_OF_LINE_P (&it)
15983 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
15984 : (text_area_width / 2))))
15985 / FRAME_COLUMN_WIDTH (it.f);
15986 else if ((!row_r2l_p
15987 && w->cursor.x >= text_area_width - h_margin)
15988 || (row_r2l_p && w->cursor.x <= h_margin))
15989 {
15990 if (hscroll_relative_p)
15991 wanted_x = text_area_width * (1 - hscroll_step_rel)
15992 - h_margin;
15993 else
15994 wanted_x = text_area_width
15995 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
15996 - h_margin;
15997 hscroll
15998 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
15999 }
16000 else
16001 {
16002 if (hscroll_relative_p)
16003 wanted_x =
16004 text_area_width * hscroll_step_rel + h_margin + x_offset;
16005 else
16006 wanted_x =
16007 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16008 + h_margin + x_offset;
16009 hscroll
16010 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16011 }
16012 hscroll = max (hscroll, w->min_hscroll);
16013
16014
16015
16016
16017 if (w->hscroll != hscroll
16018
16019
16020
16021
16022 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16023 {
16024 struct buffer *b = XBUFFER (w->contents);
16025 b->prevent_redisplay_optimizations_p = true;
16026 w->hscroll = hscroll;
16027 hscrolled_p = true;
16028 }
16029 }
16030 }
16031
16032 window = w->next;
16033 }
16034
16035
16036 return hscrolled_p;
16037 }
16038
16039
16040
16041
16042
16043
16044
16045
16046 static bool
16047 hscroll_windows (Lisp_Object window)
16048 {
16049 bool hscrolled_p = hscroll_window_tree (window);
16050 if (hscrolled_p)
16051 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16052 return hscrolled_p;
16053 }
16054
16055
16056
16057
16058
16059
16060
16061
16062
16063
16064 #ifdef GLYPH_DEBUG
16065
16066
16067
16068 static int debug_first_unchanged_at_end_vpos;
16069 static int debug_last_unchanged_at_beg_vpos;
16070
16071
16072
16073 static int debug_dvpos, debug_dy;
16074
16075
16076
16077 static ptrdiff_t debug_delta, debug_delta_bytes;
16078
16079
16080
16081
16082 static ptrdiff_t debug_end_vpos;
16083
16084
16085
16086
16087
16088 static void debug_method_add (struct window *, char const *, ...)
16089 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16090
16091 static void
16092 debug_method_add (struct window *w, char const *fmt, ...)
16093 {
16094 void *ptr = w;
16095 char *method = w->desired_matrix->method;
16096 int len = strlen (method);
16097 int size = sizeof w->desired_matrix->method;
16098 int remaining = size - len - 1;
16099 va_list ap;
16100
16101 if (len && remaining)
16102 {
16103 method[len] = '|';
16104 --remaining, ++len;
16105 }
16106
16107 va_start (ap, fmt);
16108 vsnprintf (method + len, remaining + 1, fmt, ap);
16109 va_end (ap);
16110
16111 if (trace_redisplay_p)
16112 fprintf (stderr, "%p (%s): %s\n",
16113 ptr,
16114 ((BUFFERP (w->contents)
16115 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16116 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16117 : "no buffer"),
16118 method + len);
16119 }
16120
16121 #endif
16122
16123
16124
16125
16126
16127
16128
16129 static bool
16130 text_outside_line_unchanged_p (struct window *w,
16131 ptrdiff_t start, ptrdiff_t end)
16132 {
16133 bool unchanged_p = true;
16134
16135
16136 if (window_outdated (w))
16137 {
16138
16139 if (GPT < start || Z - GPT < end)
16140 unchanged_p = false;
16141
16142
16143 if (unchanged_p
16144 && (BEG_UNCHANGED < start - 1
16145 || END_UNCHANGED < end))
16146 unchanged_p = false;
16147
16148
16149
16150 if (unchanged_p
16151 && FIXNUMP (BVAR (current_buffer, selective_display))
16152 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16153 && (BEG_UNCHANGED < start || GPT <= start))
16154 unchanged_p = false;
16155
16156
16157
16158
16159
16160
16161
16162
16163 if (unchanged_p)
16164 {
16165 if (BEG + BEG_UNCHANGED == start
16166 && overlay_touches_p (start))
16167 unchanged_p = false;
16168 if (END_UNCHANGED == end
16169 && overlay_touches_p (Z - end))
16170 unchanged_p = false;
16171 }
16172
16173
16174
16175
16176
16177
16178
16179
16180 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16181 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16182 unchanged_p = false;
16183 }
16184
16185 return unchanged_p;
16186 }
16187
16188
16189
16190
16191
16192
16193
16194
16195
16196 void
16197 redisplay (void)
16198 {
16199 redisplay_internal ();
16200 }
16201
16202
16203 static Lisp_Object
16204 overlay_arrow_string_or_property (Lisp_Object var)
16205 {
16206 Lisp_Object val;
16207
16208 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16209 return val;
16210
16211 return Voverlay_arrow_string;
16212 }
16213
16214
16215 static bool
16216 overlay_arrow_in_current_buffer_p (void)
16217 {
16218 Lisp_Object vlist;
16219
16220 for (vlist = Voverlay_arrow_variable_list;
16221 CONSP (vlist);
16222 vlist = XCDR (vlist))
16223 {
16224 Lisp_Object var = XCAR (vlist);
16225 Lisp_Object val;
16226
16227 if (!SYMBOLP (var))
16228 continue;
16229 val = find_symbol_value (var);
16230 if (MARKERP (val)
16231 && current_buffer == XMARKER (val)->buffer)
16232 return true;
16233 }
16234 return false;
16235 }
16236
16237
16238
16239
16240
16241
16242
16243 static bool
16244 overlay_arrows_changed_p (bool set_redisplay)
16245 {
16246 Lisp_Object vlist;
16247 bool changed = false;
16248
16249 for (vlist = Voverlay_arrow_variable_list;
16250 CONSP (vlist);
16251 vlist = XCDR (vlist))
16252 {
16253 Lisp_Object var = XCAR (vlist);
16254 Lisp_Object val, pstr;
16255
16256 if (!SYMBOLP (var))
16257 continue;
16258 val = find_symbol_value (var);
16259 if (!MARKERP (val))
16260 continue;
16261 if (! EQ (Fmarker_position (val),
16262
16263
16264 Fget (var, Qlast_arrow_position))
16265 || ! (pstr = overlay_arrow_string_or_property (var),
16266 EQ (pstr, Fget (var, Qlast_arrow_string))))
16267 {
16268 struct buffer *buf = XMARKER (val)->buffer;
16269
16270 if (set_redisplay)
16271 {
16272 if (buf)
16273 bset_redisplay (buf);
16274 changed = true;
16275 }
16276 else
16277 return true;
16278 }
16279 }
16280 return changed;
16281 }
16282
16283
16284
16285 static void
16286 update_overlay_arrows (int up_to_date)
16287 {
16288 Lisp_Object vlist;
16289
16290 for (vlist = Voverlay_arrow_variable_list;
16291 CONSP (vlist);
16292 vlist = XCDR (vlist))
16293 {
16294 Lisp_Object var = XCAR (vlist);
16295
16296 if (!SYMBOLP (var))
16297 continue;
16298
16299 if (up_to_date > 0)
16300 {
16301 Lisp_Object val = find_symbol_value (var);
16302 if (!MARKERP (val))
16303 continue;
16304 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16305 Fput (var, Qlast_arrow_string,
16306 overlay_arrow_string_or_property (var));
16307 }
16308 else if (up_to_date < 0
16309 || !NILP (Fget (var, Qlast_arrow_position)))
16310 {
16311 Fput (var, Qlast_arrow_position, Qt);
16312 Fput (var, Qlast_arrow_string, Qt);
16313 }
16314 }
16315 }
16316
16317
16318
16319
16320
16321
16322 static Lisp_Object
16323 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16324 {
16325 Lisp_Object vlist;
16326
16327 for (vlist = Voverlay_arrow_variable_list;
16328 CONSP (vlist);
16329 vlist = XCDR (vlist))
16330 {
16331 Lisp_Object var = XCAR (vlist);
16332 Lisp_Object val;
16333
16334 if (!SYMBOLP (var))
16335 continue;
16336
16337 val = find_symbol_value (var);
16338
16339 if (MARKERP (val)
16340 && current_buffer == XMARKER (val)->buffer
16341 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16342 {
16343 if (FRAME_WINDOW_P (it->f)
16344
16345
16346 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16347 {
16348 #ifdef HAVE_WINDOW_SYSTEM
16349 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16350 {
16351 int fringe_bitmap = lookup_fringe_bitmap (val);
16352 if (fringe_bitmap != 0)
16353 return make_fixnum (fringe_bitmap);
16354 }
16355 #endif
16356 return make_fixnum (-1);
16357 }
16358 return overlay_arrow_string_or_property (var);
16359 }
16360 }
16361
16362 return Qnil;
16363 }
16364
16365
16366
16367
16368
16369 static bool
16370 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16371 struct buffer *buf, ptrdiff_t pt)
16372 {
16373 ptrdiff_t start, end;
16374 Lisp_Object prop;
16375 Lisp_Object buffer;
16376
16377 XSETBUFFER (buffer, buf);
16378
16379
16380 if (prev_buf == buf)
16381 {
16382 if (prev_pt == pt)
16383
16384 return false;
16385
16386 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16387 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16388 && composition_valid_p (start, end, prop)
16389 && start < prev_pt && end > prev_pt)
16390
16391
16392 return (pt <= start || pt >= end);
16393 }
16394
16395
16396 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16397 && find_composition (pt, -1, &start, &end, &prop, buffer)
16398 && composition_valid_p (start, end, prop)
16399 && start < pt && end > pt);
16400 }
16401
16402
16403
16404 static void
16405 reconsider_clip_changes (struct window *w)
16406 {
16407 struct buffer *b = XBUFFER (w->contents);
16408
16409 if (b->clip_changed
16410 && w->window_end_valid
16411 && w->current_matrix->buffer == b
16412 && w->current_matrix->zv == BUF_ZV (b)
16413 && w->current_matrix->begv == BUF_BEGV (b))
16414 b->clip_changed = false;
16415
16416
16417
16418
16419
16420 if (!b->clip_changed && w->window_end_valid)
16421 {
16422 ptrdiff_t pt = (w == XWINDOW (selected_window)
16423 ? PT : marker_position (w->pointm));
16424
16425 if ((w->current_matrix->buffer != b || pt != w->last_point)
16426 && check_point_in_composition (w->current_matrix->buffer,
16427 w->last_point, b, pt))
16428 b->clip_changed = true;
16429 }
16430 }
16431
16432 static void
16433 propagate_buffer_redisplay (void)
16434 {
16435
16436
16437
16438
16439
16440
16441
16442
16443
16444 Lisp_Object ws = window_list ();
16445 for (; CONSP (ws); ws = XCDR (ws))
16446 {
16447 struct window *thisw = XWINDOW (XCAR (ws));
16448 struct buffer *thisb = XBUFFER (thisw->contents);
16449 if (thisb->text->redisplay)
16450 thisw->redisplay = true;
16451 }
16452 }
16453
16454 #define STOP_POLLING \
16455 do { if (! polling_stopped_here) stop_polling (); \
16456 polling_stopped_here = true; } while (false)
16457
16458 #define RESUME_POLLING \
16459 do { if (polling_stopped_here) start_polling (); \
16460 polling_stopped_here = false; } while (false)
16461
16462
16463
16464
16465 static void
16466 redisplay_internal (void)
16467 {
16468 struct window *w = XWINDOW (selected_window);
16469 struct window *sw;
16470 struct frame *fr;
16471 bool pending;
16472 bool must_finish = false, match_p;
16473 struct text_pos tlbufpos, tlendpos;
16474 int number_of_visible_frames;
16475 struct frame *sf;
16476 bool polling_stopped_here = false;
16477 Lisp_Object tail, frame;
16478
16479
16480
16481
16482 enum { MAX_HSCROLL_RETRIES = 16 };
16483 int hscroll_retries = 0;
16484
16485
16486
16487
16488
16489
16490 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16491 int garbaged_frame_retries = 0;
16492
16493
16494
16495 bool consider_all_windows_p;
16496
16497
16498 bool update_miniwindow_p = false;
16499
16500 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16501
16502
16503
16504
16505 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16506 && redisplay_skip_initial_frame)
16507 || !NILP (Vinhibit_redisplay))
16508 return;
16509
16510
16511
16512
16513 fr = XFRAME (w->frame);
16514 sf = SELECTED_FRAME ();
16515
16516 if (!fr->glyphs_initialized_p)
16517 return;
16518
16519 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16520 if (popup_activated ())
16521 return;
16522 #endif
16523
16524 #if defined (HAVE_HAIKU)
16525 if (popup_activated_p)
16526 return;
16527 #endif
16528
16529
16530 if (redisplaying_p)
16531 return;
16532
16533
16534
16535 specpdl_ref count = SPECPDL_INDEX ();
16536 record_unwind_protect_void (unwind_redisplay);
16537 redisplaying_p = true;
16538 block_buffer_flips ();
16539 specbind (Qinhibit_free_realized_faces, Qnil);
16540
16541
16542 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16543
16544 FOR_EACH_FRAME (tail, frame)
16545 XFRAME (frame)->already_hscrolled_p = false;
16546
16547 reset_outermost_restrictions ();
16548
16549 retry:
16550
16551 sw = w;
16552
16553 pending = false;
16554 forget_escape_and_glyphless_faces ();
16555
16556 inhibit_free_realized_faces = false;
16557
16558
16559
16560
16561 if (face_change)
16562 windows_or_buffers_changed = 47;
16563
16564 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16565 && FRAME_TTY (sf)->previous_frame != sf)
16566 {
16567
16568
16569
16570 SET_FRAME_GARBAGED (sf);
16571 #ifndef DOS_NT
16572 set_tty_color_mode (FRAME_TTY (sf), sf);
16573 #endif
16574 FRAME_TTY (sf)->previous_frame = sf;
16575 }
16576
16577
16578
16579
16580 number_of_visible_frames = 0;
16581
16582 FOR_EACH_FRAME (tail, frame)
16583 {
16584 struct frame *f = XFRAME (frame);
16585
16586 if (FRAME_REDISPLAY_P (f))
16587 {
16588 ++number_of_visible_frames;
16589
16590 if (f->fonts_changed)
16591 {
16592 adjust_frame_glyphs (f);
16593
16594
16595
16596
16597
16598
16599 SET_FRAME_GARBAGED (f);
16600 f->fonts_changed = false;
16601 }
16602
16603
16604 if (f != sf && f->cursor_type_changed)
16605 fset_redisplay (f);
16606 }
16607 clear_desired_matrices (f);
16608 }
16609
16610
16611 do_pending_window_change (true);
16612
16613
16614 clear_garbaged_frames ();
16615
16616
16617 if (NILP (Vmemory_full))
16618 prepare_menu_bars ();
16619
16620
16621
16622
16623
16624 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16625 sw = w;
16626
16627 reconsider_clip_changes (w);
16628
16629
16630 match_p = XBUFFER (w->contents) == current_buffer;
16631 if (match_p)
16632 {
16633
16634 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16635 w->update_mode_line = true;
16636
16637 if (mode_line_update_needed (w))
16638 w->update_mode_line = true;
16639
16640
16641
16642
16643 if (current_buffer->clip_changed)
16644 bset_update_mode_line (current_buffer);
16645 }
16646
16647
16648
16649
16650
16651
16652 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16653 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16654 || (message_cleared_p
16655 && minibuf_level == 0
16656
16657
16658 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16659 {
16660 echo_area_display (false);
16661
16662 if (message_cleared_p)
16663 update_miniwindow_p = true;
16664
16665 must_finish = true;
16666
16667
16668
16669
16670
16671 if (!display_last_displayed_message_p)
16672 message_cleared_p = false;
16673 }
16674 else if (EQ (selected_window, minibuf_window)
16675 && (current_buffer->clip_changed || window_outdated (w))
16676 && resize_mini_window (w, false))
16677 {
16678
16679
16680 must_finish = true;
16681
16682
16683
16684
16685 clear_garbaged_frames ();
16686 }
16687
16688 if (!NILP (Vrun_hooks))
16689 run_window_change_functions ();
16690
16691 if (windows_or_buffers_changed && !update_mode_lines)
16692
16693
16694
16695 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16696 ? REDISPLAY_SOME : 32);
16697
16698
16699
16700
16701
16702 overlay_arrows_changed_p (true);
16703
16704 consider_all_windows_p = (update_mode_lines
16705 || windows_or_buffers_changed);
16706
16707 #define AINC(a,i) \
16708 { \
16709 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16710 if (FIXNUMP (entry)) \
16711 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16712 }
16713
16714 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16715 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16716
16717
16718
16719
16720
16721 tlbufpos = this_line_start_pos;
16722 tlendpos = this_line_end_pos;
16723 if (!consider_all_windows_p
16724 && CHARPOS (tlbufpos) > 0
16725 && !w->update_mode_line
16726 && !current_buffer->clip_changed
16727 && !current_buffer->prevent_redisplay_optimizations_p
16728 && FRAME_REDISPLAY_P (XFRAME (w->frame))
16729 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16730 && !XFRAME (w->frame)->cursor_type_changed
16731 && !XFRAME (w->frame)->face_change
16732
16733 && this_line_buffer == current_buffer
16734 && match_p
16735 && !w->force_start
16736 && !w->optional_new_start
16737
16738 && PT >= CHARPOS (tlbufpos)
16739 && PT <= Z - CHARPOS (tlendpos)
16740
16741
16742
16743
16744
16745
16746 && (NILP (Vdisplay_line_numbers)
16747 || EQ (Vdisplay_line_numbers, Qvisual))
16748
16749
16750 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16751 CHARPOS (tlendpos)))
16752 {
16753 if (CHARPOS (tlbufpos) > BEGV
16754 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16755 && (CHARPOS (tlbufpos) == ZV
16756 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16757
16758 goto cancel;
16759 else if (window_outdated (w) || MINI_WINDOW_P (w))
16760 {
16761
16762
16763
16764
16765
16766
16767
16768
16769
16770
16771
16772
16773
16774
16775
16776 struct it it;
16777 int line_height_before = this_line_pixel_height;
16778
16779
16780
16781 start_display (&it, w, tlbufpos);
16782
16783
16784 if (it.current_x != this_line_start_x)
16785 goto cancel;
16786
16787
16788
16789
16790 if (it.sp > 1
16791 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16792 goto cancel;
16793 redisplay_trace ("trying display optimization 1\n");
16794 w->cursor.vpos = -1;
16795 overlay_arrow_seen = false;
16796 it.vpos = this_line_vpos;
16797 it.current_y = this_line_y;
16798 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16799 display_line (&it, -1);
16800
16801
16802
16803 if (w->cursor.vpos >= 0
16804
16805
16806 && CHARPOS (this_line_start_pos)
16807
16808 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16809
16810
16811 && this_line_pixel_height == line_height_before
16812
16813
16814
16815
16816 && !hscrolling_current_line_p (w))
16817 {
16818
16819
16820 if (it.current_y < it.last_visible_y)
16821 {
16822 struct glyph_row *row
16823 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
16824 ptrdiff_t delta, delta_bytes;
16825
16826
16827
16828
16829
16830
16831 delta = (Z
16832 - CHARPOS (tlendpos)
16833 - MATRIX_ROW_START_CHARPOS (row));
16834 delta_bytes = (Z_BYTE
16835 - BYTEPOS (tlendpos)
16836 - MATRIX_ROW_START_BYTEPOS (row));
16837
16838 increment_matrix_positions (w->current_matrix,
16839 this_line_vpos + 1,
16840 w->current_matrix->nrows,
16841 delta, delta_bytes);
16842 }
16843
16844
16845
16846
16847 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
16848 {
16849 if (w->window_end_vpos < this_line_vpos)
16850 w->window_end_vpos = this_line_vpos;
16851 }
16852 else if (w->window_end_vpos == this_line_vpos
16853 && this_line_vpos > 0)
16854 w->window_end_vpos = this_line_vpos - 1;
16855 w->window_end_valid = false;
16856
16857
16858 w->desired_matrix->no_scrolling_p = true;
16859
16860 #ifdef GLYPH_DEBUG
16861 *w->desired_matrix->method = 0;
16862 debug_method_add (w, "optimization 1");
16863 #endif
16864 #ifdef HAVE_WINDOW_SYSTEM
16865 update_window_fringes (w, false);
16866 #endif
16867 goto update;
16868 }
16869 else
16870 goto cancel;
16871 }
16872 else if (
16873 PT == w->last_point
16874
16875
16876
16877
16878 && 0 <= w->cursor.vpos
16879 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
16880 {
16881 if (!must_finish)
16882 {
16883 do_pending_window_change (true);
16884
16885 if (WINDOWP (selected_window)
16886 && (w = XWINDOW (selected_window)) != sw)
16887 goto retry;
16888
16889
16890
16891 if (w->cursor_off_p == w->last_cursor_off_p)
16892 goto end_of_redisplay;
16893 }
16894 goto update;
16895 }
16896
16897
16898 else if (NILP (Vshow_trailing_whitespace)
16899 && !cursor_in_echo_area
16900 && !composition_break_at_point)
16901 {
16902 struct it it;
16903 struct glyph_row *row;
16904
16905
16906
16907
16908 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
16909 NULL, DEFAULT_FACE_ID);
16910 it.current_x = this_line_start_x;
16911 it.current_y = this_line_y;
16912 it.vpos = this_line_vpos;
16913
16914 if (current_buffer->long_line_optimizations_p
16915 && it.line_wrap == TRUNCATE
16916 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
16917 {
16918
16919
16920
16921 reseat_at_next_visible_line_start (&it, false);
16922 if (IT_CHARPOS (it) <= PT)
16923 it.vpos = this_line_vpos + 1;
16924 }
16925 else
16926 {
16927
16928
16929 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
16930 }
16931
16932 if (it.vpos == this_line_vpos
16933 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
16934 row->enabled_p))
16935 {
16936 eassert (this_line_vpos == it.vpos);
16937 eassert (this_line_y == it.current_y);
16938 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
16939 if (cursor_row_fully_visible_p (w, false, true, false))
16940 {
16941 #ifdef GLYPH_DEBUG
16942 *w->desired_matrix->method = 0;
16943 debug_method_add (w, "optimization 3");
16944 #endif
16945 goto update;
16946 }
16947 else
16948 goto cancel;
16949 }
16950 else
16951 goto cancel;
16952 }
16953
16954 cancel:
16955
16956 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
16957 }
16958
16959 CHARPOS (this_line_start_pos) = 0;
16960 ++clear_face_cache_count;
16961 #ifdef HAVE_WINDOW_SYSTEM
16962 ++clear_image_cache_count;
16963 #endif
16964
16965
16966
16967
16968
16969
16970 if (consider_all_windows_p)
16971 {
16972 FOR_EACH_FRAME (tail, frame)
16973 XFRAME (frame)->updated_p = false;
16974
16975 propagate_buffer_redisplay ();
16976
16977 FOR_EACH_FRAME (tail, frame)
16978 {
16979 struct frame *f = XFRAME (frame);
16980
16981
16982
16983 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
16984 && !EQ (FRAME_TTY (f)->top_frame, frame))
16985 continue;
16986
16987 retry_frame:
16988 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
16989 {
16990 bool gcscrollbars
16991
16992 = f->redisplay || !REDISPLAY_SOME_P ();
16993 bool f_redisplay_flag = f->redisplay;
16994
16995
16996
16997
16998 if (!FRAME_LIVE_P (f))
16999 continue;
17000
17001
17002
17003 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
17004 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
17005
17006 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17007 {
17008
17009
17010
17011
17012
17013
17014
17015 f->inhibit_clear_image_cache = true;
17016 redisplay_windows (FRAME_ROOT_WINDOW (f));
17017 }
17018
17019
17020 else if (!REDISPLAY_SOME_P ())
17021 f->redisplay = true;
17022
17023
17024 if (!FRAME_LIVE_P (f))
17025 continue;
17026
17027
17028
17029 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17030 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17031
17032 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17033 {
17034
17035 if (f->fonts_changed)
17036 {
17037 adjust_frame_glyphs (f);
17038
17039
17040
17041 SET_FRAME_GARBAGED (f);
17042 f->fonts_changed = false;
17043 goto retry_frame;
17044 }
17045
17046
17047 if (!f->already_hscrolled_p)
17048 {
17049 f->already_hscrolled_p = true;
17050 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17051 && hscroll_windows (f->root_window))
17052 {
17053 hscroll_retries++;
17054 goto retry_frame;
17055 }
17056 }
17057
17058
17059
17060
17061
17062
17063
17064
17065
17066
17067
17068
17069 if (!f_redisplay_flag && f->redisplay)
17070 goto retry_frame;
17071
17072
17073
17074
17075
17076
17077
17078
17079
17080 if (FRAME_GARBAGED_P (f)
17081 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17082 goto retry;
17083
17084 #ifdef HAVE_WINDOW_SYSTEM
17085 if (FRAME_WINDOW_P (f)
17086 && FRAME_RIF (f)->clear_under_internal_border)
17087 FRAME_RIF (f)->clear_under_internal_border (f);
17088 #endif
17089
17090
17091
17092 if (interrupt_input)
17093 unrequest_sigio ();
17094 STOP_POLLING;
17095
17096 pending |= update_frame (f, false, false);
17097
17098
17099
17100
17101
17102
17103
17104 if (FRAME_GARBAGED_P (f))
17105 {
17106 fset_redisplay (f);
17107 f->garbaged = false;
17108 goto retry_frame;
17109 }
17110 f->cursor_type_changed = false;
17111 f->updated_p = true;
17112 f->inhibit_clear_image_cache = false;
17113 }
17114 }
17115 }
17116
17117 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17118
17119 if (!pending)
17120 {
17121
17122
17123
17124 FOR_EACH_FRAME (tail, frame)
17125 {
17126 struct frame *f = XFRAME (frame);
17127 if (f->updated_p)
17128 {
17129 f->redisplay = false;
17130 f->garbaged = false;
17131 mark_window_display_accurate (f->root_window, true);
17132 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17133 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17134 }
17135 }
17136 }
17137 }
17138 else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17139 {
17140 sf->inhibit_clear_image_cache = true;
17141 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17142
17143
17144 internal_condition_case_1 (redisplay_window_1, selected_window,
17145 list_of_error,
17146 redisplay_window_error);
17147 if (update_miniwindow_p)
17148 {
17149 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17150
17151 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17152 internal_condition_case_1 (redisplay_window_1, mini_window,
17153 list_of_error,
17154 redisplay_window_error);
17155 }
17156
17157
17158
17159 update:
17160
17161
17162
17163 if (sf->fonts_changed || sf->redisplay)
17164 {
17165 if (sf->redisplay)
17166 {
17167
17168
17169
17170
17171
17172
17173 windows_or_buffers_changed = 50;
17174 }
17175 goto retry;
17176 }
17177
17178
17179
17180 inhibit_free_realized_faces = true;
17181
17182
17183
17184
17185 if (interrupt_input)
17186 unrequest_sigio ();
17187 STOP_POLLING;
17188
17189 if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17190 {
17191 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17192 && hscroll_windows (selected_window))
17193 {
17194 hscroll_retries++;
17195 goto retry;
17196 }
17197
17198 XWINDOW (selected_window)->must_be_updated_p = true;
17199 pending = update_frame (sf, false, false);
17200 sf->cursor_type_changed = false;
17201 sf->inhibit_clear_image_cache = false;
17202 }
17203
17204
17205
17206
17207
17208
17209 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17210 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17211
17212 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17213 {
17214 XWINDOW (mini_window)->must_be_updated_p = true;
17215 pending |= update_frame (mini_frame, false, false);
17216 mini_frame->cursor_type_changed = false;
17217 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17218 && hscroll_windows (mini_window))
17219 {
17220 hscroll_retries++;
17221 goto retry;
17222 }
17223 }
17224 }
17225
17226
17227
17228 if (pending)
17229 {
17230
17231
17232
17233 CHARPOS (this_line_start_pos) = 0;
17234
17235
17236 update_overlay_arrows (0);
17237
17238
17239
17240 if (!WINDOW_FULL_WIDTH_P (w)
17241 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17242 update_mode_lines = 36;
17243 }
17244 else
17245 {
17246 if (!consider_all_windows_p)
17247 {
17248
17249
17250 if (XBUFFER (w->contents)->text->redisplay
17251 && buffer_window_count (XBUFFER (w->contents)) > 1)
17252
17253
17254 propagate_buffer_redisplay ();
17255 mark_window_display_accurate_1 (w, true);
17256
17257
17258 update_overlay_arrows (1);
17259
17260 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17261 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17262 }
17263
17264 update_mode_lines = 0;
17265 windows_or_buffers_changed = 0;
17266 }
17267
17268
17269
17270
17271
17272 if (interrupt_input)
17273 request_sigio ();
17274 RESUME_POLLING;
17275
17276
17277
17278
17279
17280
17281
17282 if (!pending)
17283 {
17284 int new_count = 0;
17285
17286 FOR_EACH_FRAME (tail, frame)
17287 {
17288 if (FRAME_REDISPLAY_P (XFRAME (frame)))
17289 new_count++;
17290 }
17291
17292 if (new_count != number_of_visible_frames)
17293 windows_or_buffers_changed = 52;
17294 }
17295
17296
17297 do_pending_window_change (true);
17298
17299
17300
17301 if ((windows_or_buffers_changed && !pending)
17302 || (WINDOWP (selected_window)
17303 && (w = XWINDOW (selected_window)) != sw))
17304 goto retry;
17305
17306
17307
17308
17309
17310
17311
17312 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17313 {
17314 clear_face_cache (false);
17315 clear_face_cache_count = 0;
17316 }
17317
17318 #ifdef HAVE_WINDOW_SYSTEM
17319 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17320 {
17321 clear_image_caches (Qnil);
17322 clear_image_cache_count = 0;
17323 }
17324 #endif
17325
17326 end_of_redisplay:
17327 #ifdef HAVE_NS
17328 ns_set_doc_edited ();
17329 #endif
17330 if (interrupt_input && interrupts_deferred)
17331 request_sigio ();
17332
17333
17334
17335 if (max_redisplay_ticks > 0)
17336 update_redisplay_ticks (0, NULL);
17337
17338 unbind_to (count, Qnil);
17339 RESUME_POLLING;
17340 }
17341
17342 static void
17343 unwind_redisplay_preserve_echo_area (void)
17344 {
17345 unblock_buffer_flips ();
17346 }
17347
17348
17349
17350
17351
17352
17353
17354
17355
17356
17357
17358
17359 void
17360 redisplay_preserve_echo_area (int from_where)
17361 {
17362 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17363
17364 block_input ();
17365 specpdl_ref count = SPECPDL_INDEX ();
17366 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17367 block_buffer_flips ();
17368 unblock_input ();
17369
17370 if (!NILP (echo_area_buffer[1]))
17371 {
17372
17373
17374 display_last_displayed_message_p = true;
17375 redisplay_internal ();
17376 display_last_displayed_message_p = false;
17377 }
17378 else
17379 redisplay_internal ();
17380
17381 flush_frame (SELECTED_FRAME ());
17382 unbind_to (count, Qnil);
17383 }
17384
17385
17386
17387
17388 static void
17389 unwind_redisplay (void)
17390 {
17391 redisplaying_p = false;
17392 unblock_buffer_flips ();
17393 }
17394
17395
17396
17397 void
17398 unwind_display_working_on_window (void)
17399 {
17400 display_working_on_window_p = false;
17401 }
17402
17403
17404
17405
17406
17407
17408 static void
17409 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17410 {
17411 struct buffer *b = XBUFFER (w->contents);
17412
17413 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17414 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17415 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17416
17417 if (accurate_p)
17418 {
17419 b->clip_changed = false;
17420 b->prevent_redisplay_optimizations_p = false;
17421 eassert (buffer_window_count (b) > 0);
17422
17423
17424
17425 b->text->redisplay = false;
17426
17427 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17428 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17429 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17430 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17431
17432 w->current_matrix->buffer = b;
17433 w->current_matrix->begv = BUF_BEGV (b);
17434 w->current_matrix->zv = BUF_ZV (b);
17435 w->current_matrix->header_line_p = window_wants_header_line (w);
17436 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17437
17438 w->last_cursor_vpos = w->cursor.vpos;
17439 w->last_cursor_off_p = w->cursor_off_p;
17440
17441 if (w == XWINDOW (selected_window))
17442 w->last_point = BUF_PT (b);
17443 else
17444 w->last_point = marker_position (w->pointm);
17445
17446 w->window_end_valid = true;
17447 w->update_mode_line = false;
17448 w->preserve_vscroll_p = false;
17449 }
17450
17451 w->redisplay = !accurate_p;
17452 }
17453
17454
17455
17456
17457
17458
17459
17460 void
17461 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17462 {
17463 struct window *w;
17464
17465 for (; !NILP (window); window = w->next)
17466 {
17467 w = XWINDOW (window);
17468 if (WINDOWP (w->contents))
17469 mark_window_display_accurate (w->contents, accurate_p);
17470 else
17471 mark_window_display_accurate_1 (w, accurate_p);
17472 }
17473
17474 if (accurate_p)
17475 update_overlay_arrows (1);
17476 else
17477
17478
17479
17480 update_overlay_arrows (-1);
17481 }
17482
17483
17484
17485
17486
17487
17488
17489 Lisp_Object
17490 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17491 {
17492 Lisp_Object val;
17493
17494 if (ASCII_CHAR_P (c))
17495 {
17496 val = dp->ascii;
17497 if (SUB_CHAR_TABLE_P (val))
17498 val = XSUB_CHAR_TABLE (val)->contents[c];
17499 }
17500 else
17501 {
17502 Lisp_Object table;
17503
17504 XSETCHAR_TABLE (table, dp);
17505 val = char_table_ref (table, c);
17506 }
17507 if (NILP (val))
17508 val = dp->defalt;
17509 return val;
17510 }
17511
17512 static int buffer_flip_blocked_depth;
17513
17514 static void
17515 block_buffer_flips (void)
17516 {
17517 eassert (buffer_flip_blocked_depth >= 0);
17518 buffer_flip_blocked_depth++;
17519 }
17520
17521 static void
17522 unblock_buffer_flips (void)
17523 {
17524 eassert (buffer_flip_blocked_depth > 0);
17525 if (--buffer_flip_blocked_depth == 0)
17526 {
17527 Lisp_Object tail, frame;
17528 block_input ();
17529 FOR_EACH_FRAME (tail, frame)
17530 {
17531 struct frame *f = XFRAME (frame);
17532 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17533 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17534 }
17535 unblock_input ();
17536 }
17537 }
17538
17539 bool
17540 buffer_flipping_blocked_p (void)
17541 {
17542 return buffer_flip_blocked_depth > 0;
17543 }
17544
17545
17546
17547
17548
17549
17550
17551
17552 static void
17553 redisplay_windows (Lisp_Object window)
17554 {
17555 while (!NILP (window))
17556 {
17557 struct window *w = XWINDOW (window);
17558
17559 if (WINDOWP (w->contents))
17560 redisplay_windows (w->contents);
17561 else if (BUFFERP (w->contents))
17562 {
17563 displayed_buffer = XBUFFER (w->contents);
17564
17565
17566 internal_condition_case_1 (redisplay_window_0, window,
17567 list_of_error,
17568 redisplay_window_error);
17569 }
17570
17571 window = w->next;
17572 }
17573 }
17574
17575 static Lisp_Object
17576 redisplay_window_error (Lisp_Object error_data)
17577 {
17578 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17579
17580
17581
17582 if (max_redisplay_ticks > 0
17583 && CONSP (error_data)
17584 && EQ (XCAR (error_data), Qerror)
17585 && STRINGP (XCAR (XCDR (error_data))))
17586 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17587 XCAR (XCDR (error_data))),
17588 Vdelayed_warnings_list);
17589 return Qnil;
17590 }
17591
17592 static Lisp_Object
17593 redisplay_window_0 (Lisp_Object window)
17594 {
17595 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17596 redisplay_window (window, false);
17597 return Qnil;
17598 }
17599
17600 static Lisp_Object
17601 redisplay_window_1 (Lisp_Object window)
17602 {
17603 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17604 redisplay_window (window, true);
17605 return Qnil;
17606 }
17607
17608
17609
17610
17611
17612
17613
17614
17615
17616
17617
17618
17619
17620
17621
17622
17623
17624
17625
17626 void
17627 update_redisplay_ticks (int ticks, struct window *w)
17628 {
17629
17630 static struct window *cwindow;
17631 static EMACS_INT window_ticks;
17632
17633
17634
17635
17636 if (!ticks && w != cwindow)
17637 {
17638 cwindow = w;
17639 window_ticks = 0;
17640 }
17641
17642
17643 if ((!w && !redisplaying_p && !display_working_on_window_p)
17644
17645
17646 || (w && MINI_WINDOW_P (w)))
17647 return;
17648
17649 if (ticks > 0)
17650 window_ticks += ticks;
17651 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17652 {
17653
17654
17655
17656 Lisp_Object contents = w ? w->contents : Qnil;
17657 char *bufname =
17658 NILP (contents)
17659 ? SSDATA (BVAR (current_buffer, name))
17660 : (BUFFERP (contents)
17661 ? SSDATA (BVAR (XBUFFER (contents), name))
17662 : (char *) "<unknown>");
17663
17664 windows_or_buffers_changed = 177;
17665
17666
17667
17668 if (w && w->desired_matrix)
17669 w->desired_matrix->no_scrolling_p = true;
17670 error ("Window showing buffer %s takes too long to redisplay", bufname);
17671 }
17672 }
17673
17674
17675
17676
17677
17678
17679
17680
17681
17682
17683 static bool
17684 set_cursor_from_row (struct window *w, struct glyph_row *row,
17685 struct glyph_matrix *matrix,
17686 ptrdiff_t delta, ptrdiff_t delta_bytes,
17687 int dy, int dvpos)
17688 {
17689 struct glyph *glyph = row->glyphs[TEXT_AREA];
17690 struct glyph *end = glyph + row->used[TEXT_AREA];
17691 struct glyph *cursor = NULL;
17692
17693 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17694 int x = row->x;
17695 ptrdiff_t pt_old = PT - delta;
17696 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17697 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17698 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17699
17700
17701 struct glyph *glyphs_end = end;
17702
17703
17704 bool match_with_avoid_cursor = false;
17705
17706
17707 bool string_seen = false;
17708
17709
17710 ptrdiff_t bpos_max = pos_before;
17711 ptrdiff_t bpos_min = pos_after;
17712
17713
17714 ptrdiff_t bpos_covered = 0;
17715
17716
17717 bool string_from_text_prop = false;
17718
17719
17720
17721
17722 eassert (!row->mode_line_p);
17723 if (row->mode_line_p)
17724 return false;
17725
17726
17727
17728
17729 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17730 {
17731 if (!row->reversed_p)
17732 {
17733 while (glyph < end
17734 && NILP (glyph->object)
17735 && glyph->charpos < 0)
17736 {
17737 x += glyph->pixel_width;
17738 ++glyph;
17739 }
17740 while (end > glyph
17741 && NILP ((end - 1)->object)
17742
17743
17744 && (end - 1)->charpos <= 0)
17745 --end;
17746 glyph_before = glyph - 1;
17747 glyph_after = end;
17748 }
17749 else
17750 {
17751 struct glyph *g;
17752
17753
17754
17755 glyphs_end = end = glyph - 1;
17756 glyph += row->used[TEXT_AREA] - 1;
17757
17758 while (glyph > end + 1
17759 && NILP (glyph->object)
17760 && glyph->charpos < 0)
17761 --glyph;
17762 if (NILP (glyph->object) && glyph->charpos < 0)
17763 --glyph;
17764
17765
17766 for (x = 0, g = end + 1; g < glyph; g++)
17767 x += g->pixel_width;
17768 while (end < glyph
17769 && NILP ((end + 1)->object)
17770 && (end + 1)->charpos <= 0)
17771 ++end;
17772 glyph_before = glyph + 1;
17773 glyph_after = end;
17774 }
17775 }
17776 else if (row->reversed_p)
17777 {
17778
17779
17780
17781 cursor = end - 1;
17782
17783
17784
17785 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
17786 && !WINDOW_RIGHTMOST_P (w)
17787 && cursor == row->glyphs[LAST_AREA] - 1)
17788 cursor--;
17789 x = -1;
17790 }
17791
17792
17793
17794
17795
17796 if (!row->reversed_p)
17797 while (
17798 glyph < end
17799
17800 && !NILP (glyph->object))
17801 {
17802 if (BUFFERP (glyph->object))
17803 {
17804 ptrdiff_t dpos = glyph->charpos - pt_old;
17805
17806 if (glyph->charpos > bpos_max)
17807 bpos_max = glyph->charpos;
17808 if (glyph->charpos < bpos_min)
17809 bpos_min = glyph->charpos;
17810 if (!glyph->avoid_cursor_p)
17811 {
17812
17813
17814 if (dpos == 0)
17815 {
17816 match_with_avoid_cursor = false;
17817 break;
17818 }
17819
17820
17821 if (0 > dpos && dpos > pos_before - pt_old)
17822 {
17823 pos_before = glyph->charpos;
17824 glyph_before = glyph;
17825 }
17826 else if (0 < dpos && dpos < pos_after - pt_old)
17827 {
17828 pos_after = glyph->charpos;
17829 glyph_after = glyph;
17830 }
17831 }
17832 else if (dpos == 0)
17833 match_with_avoid_cursor = true;
17834 }
17835 else if (STRINGP (glyph->object))
17836 {
17837 Lisp_Object chprop;
17838 ptrdiff_t glyph_pos = glyph->charpos;
17839
17840 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
17841 glyph->object);
17842 if (!NILP (chprop))
17843 {
17844
17845
17846
17847
17848
17849
17850
17851
17852
17853
17854 ptrdiff_t prop_pos =
17855 string_buffer_position_lim (glyph->object, pos_before,
17856 pos_after, false);
17857
17858 if (prop_pos >= pos_before)
17859 bpos_max = prop_pos;
17860 }
17861 if (FIXNUMP (chprop))
17862 {
17863 bpos_covered = bpos_max + XFIXNUM (chprop);
17864
17865
17866
17867
17868
17869
17870
17871
17872
17873
17874
17875 if (bpos_max <= pt_old && bpos_covered >= pt_old)
17876 {
17877 cursor = glyph;
17878 break;
17879 }
17880 }
17881
17882 string_seen = true;
17883 }
17884 x += glyph->pixel_width;
17885 ++glyph;
17886 }
17887 else if (glyph > end)
17888 while (!NILP (glyph->object))
17889 {
17890 if (BUFFERP (glyph->object))
17891 {
17892 ptrdiff_t dpos = glyph->charpos - pt_old;
17893
17894 if (glyph->charpos > bpos_max)
17895 bpos_max = glyph->charpos;
17896 if (glyph->charpos < bpos_min)
17897 bpos_min = glyph->charpos;
17898 if (!glyph->avoid_cursor_p)
17899 {
17900 if (dpos == 0)
17901 {
17902 match_with_avoid_cursor = false;
17903 break;
17904 }
17905 if (0 > dpos && dpos > pos_before - pt_old)
17906 {
17907 pos_before = glyph->charpos;
17908 glyph_before = glyph;
17909 }
17910 else if (0 < dpos && dpos < pos_after - pt_old)
17911 {
17912 pos_after = glyph->charpos;
17913 glyph_after = glyph;
17914 }
17915 }
17916 else if (dpos == 0)
17917 match_with_avoid_cursor = true;
17918 }
17919 else if (STRINGP (glyph->object))
17920 {
17921 Lisp_Object chprop;
17922 ptrdiff_t glyph_pos = glyph->charpos;
17923
17924 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
17925 glyph->object);
17926 if (!NILP (chprop))
17927 {
17928 ptrdiff_t prop_pos =
17929 string_buffer_position_lim (glyph->object, pos_before,
17930 pos_after, false);
17931
17932 if (prop_pos >= pos_before)
17933 bpos_max = prop_pos;
17934 }
17935 if (FIXNUMP (chprop))
17936 {
17937 bpos_covered = bpos_max + XFIXNUM (chprop);
17938
17939
17940
17941 if (bpos_max <= pt_old && bpos_covered >= pt_old)
17942 {
17943 cursor = glyph;
17944 break;
17945 }
17946 }
17947 string_seen = true;
17948 }
17949 --glyph;
17950 if (glyph == glyphs_end)
17951 {
17952 x--;
17953 break;
17954 }
17955 x -= glyph->pixel_width;
17956 }
17957
17958
17959
17960
17961 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
17962 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
17963 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
17964 {
17965
17966
17967
17968
17969
17970 bool empty_line_p =
17971 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
17972 && NILP (glyph->object) && glyph->charpos > 0
17973
17974
17975
17976
17977 && !(row->continued_p || row->truncated_on_right_p));
17978
17979 if (row->ends_in_ellipsis_p && pos_after == last_pos)
17980 {
17981 ptrdiff_t ellipsis_pos;
17982
17983
17984 if (!row->reversed_p)
17985 {
17986 ellipsis_pos = (glyph - 1)->charpos;
17987 while (glyph > row->glyphs[TEXT_AREA]
17988 && (glyph - 1)->charpos == ellipsis_pos)
17989 glyph--, x -= glyph->pixel_width;
17990
17991
17992
17993 x += glyph->pixel_width;
17994 glyph++;
17995 }
17996 else
17997 {
17998 ellipsis_pos = (glyph + 1)->charpos;
17999 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18000 && (glyph + 1)->charpos == ellipsis_pos)
18001 glyph++, x += glyph->pixel_width;
18002 x -= glyph->pixel_width;
18003 glyph--;
18004 }
18005 }
18006 else if (match_with_avoid_cursor)
18007 {
18008 cursor = glyph_after;
18009 x = -1;
18010 }
18011 else if (string_seen)
18012 {
18013 int incr = row->reversed_p ? -1 : +1;
18014
18015
18016
18017
18018
18019
18020 struct glyph *start, *stop;
18021 ptrdiff_t pos = pos_before;
18022
18023 x = -1;
18024
18025
18026
18027
18028
18029
18030 if (row->ends_in_newline_from_string_p)
18031 {
18032 glyph_after = end;
18033 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18034 }
18035
18036
18037
18038
18039
18040
18041
18042
18043
18044 if (!row->reversed_p)
18045 {
18046 start = min (glyph_before, glyph_after);
18047 stop = max (glyph_before, glyph_after);
18048 }
18049 else
18050 {
18051 start = max (glyph_before, glyph_after);
18052 stop = min (glyph_before, glyph_after);
18053 }
18054 for (glyph = start + incr;
18055 row->reversed_p ? glyph > stop : glyph < stop; )
18056 {
18057
18058
18059
18060
18061 if (STRINGP (glyph->object))
18062 {
18063 Lisp_Object str;
18064 ptrdiff_t tem;
18065
18066
18067 ptrdiff_t lim = pos_after
18068 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18069
18070 string_from_text_prop = false;
18071 str = glyph->object;
18072 tem = string_buffer_position_lim (str, pos, lim, false);
18073 if (tem == 0
18074 || pos <= tem)
18075 {
18076
18077
18078
18079
18080
18081
18082
18083
18084
18085
18086 if (tem == 0
18087 || tem == pt_old
18088 || (tem - pt_old > 0 && tem < pos_after))
18089 {
18090
18091
18092
18093
18094
18095
18096 ptrdiff_t strpos = glyph->charpos;
18097
18098 if (tem)
18099 {
18100 cursor = glyph;
18101 string_from_text_prop = true;
18102 }
18103 for ( ;
18104 (row->reversed_p ? glyph > stop : glyph < stop)
18105 && EQ (glyph->object, str);
18106 glyph += incr)
18107 {
18108 Lisp_Object cprop;
18109 ptrdiff_t gpos = glyph->charpos;
18110
18111 cprop = Fget_char_property (make_fixnum (gpos),
18112 Qcursor,
18113 glyph->object);
18114 if (!NILP (cprop))
18115 {
18116 cursor = glyph;
18117 break;
18118 }
18119 if (tem && glyph->charpos < strpos)
18120 {
18121 strpos = glyph->charpos;
18122 cursor = glyph;
18123 }
18124 }
18125
18126 if (tem == pt_old
18127 || (tem - pt_old > 0 && tem < pos_after))
18128 goto compute_x;
18129 }
18130 if (tem)
18131 pos = tem + 1;
18132 }
18133
18134
18135 while ((row->reversed_p ? glyph > stop : glyph < stop)
18136 && EQ (glyph->object, str))
18137 glyph += incr;
18138 }
18139 else
18140 glyph += incr;
18141 }
18142
18143
18144
18145 if (cursor == NULL
18146 && (row->reversed_p ? glyph <= end : glyph >= end)
18147 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18148 && STRINGP (end->object)
18149 && row->continued_p)
18150 return false;
18151 }
18152
18153
18154
18155
18156
18157 else if (row->truncated_on_left_p && pt_old < bpos_min)
18158 {
18159 cursor = glyph_before;
18160 x = -1;
18161 }
18162 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18163
18164 || (!empty_line_p
18165 && (row->reversed_p
18166 ? glyph_after > glyphs_end
18167 : glyph_after < glyphs_end)))
18168 {
18169 cursor = glyph_after;
18170 x = -1;
18171 }
18172 }
18173
18174 compute_x:
18175 if (cursor != NULL)
18176 glyph = cursor;
18177 else if (glyph == glyphs_end
18178 && pos_before == pos_after
18179 && STRINGP ((row->reversed_p
18180 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18181 : row->glyphs[TEXT_AREA])->object))
18182 {
18183
18184
18185
18186
18187 glyph =
18188 row->reversed_p
18189 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18190 : row->glyphs[TEXT_AREA];
18191 }
18192 if (x < 0)
18193 {
18194 struct glyph *g;
18195
18196
18197 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18198 {
18199 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18200 emacs_abort ();
18201 x += g->pixel_width;
18202 }
18203 }
18204
18205
18206
18207
18208
18209
18210 if (
18211 w->cursor.vpos >= 0
18212
18213 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18214
18215
18216
18217
18218
18219 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18220 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18221 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18222 {
18223 struct glyph *g1
18224 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18225
18226
18227 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18228 return false;
18229
18230
18231 if (
18232 w->cursor.hpos >= 0
18233 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18234 && ((BUFFERP (g1->object)
18235 && (g1->charpos == pt_old
18236 || (BUFFERP (glyph->object)
18237 && eabs (g1->charpos - pt_old)
18238 < eabs (glyph->charpos - pt_old))))
18239
18240
18241 || (STRINGP (g1->object)
18242 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18243 Qcursor, g1->object))
18244
18245
18246
18247 || (EQ (g1->object, glyph->object)
18248 && string_from_text_prop)
18249
18250
18251 || (NILP (glyph->object)
18252 && glyph->charpos != pt_old)))))
18253 return false;
18254
18255 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18256
18257
18258
18259 || (!row->continued_p
18260 && NILP (glyph->object)
18261 && glyph->charpos == 0
18262 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18263
18264
18265
18266
18267
18268 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18269 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18270 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18271 return false;
18272 }
18273 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18274 w->cursor.x = x;
18275 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18276 w->cursor.y = row->y + dy;
18277
18278 if (w == XWINDOW (selected_window))
18279 {
18280 if (!row->continued_p
18281 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18282 && row->x == 0)
18283 {
18284 this_line_buffer = XBUFFER (w->contents);
18285
18286 CHARPOS (this_line_start_pos)
18287 = MATRIX_ROW_START_CHARPOS (row) + delta;
18288 BYTEPOS (this_line_start_pos)
18289 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18290
18291 CHARPOS (this_line_end_pos)
18292 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18293 BYTEPOS (this_line_end_pos)
18294 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18295
18296 this_line_y = w->cursor.y;
18297 this_line_pixel_height = row->height;
18298 this_line_vpos = w->cursor.vpos;
18299 this_line_start_x = row->x;
18300 }
18301 else
18302 CHARPOS (this_line_start_pos) = 0;
18303 }
18304
18305 return true;
18306 }
18307
18308
18309
18310
18311
18312
18313
18314 static struct text_pos
18315 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18316 {
18317 struct window *w = XWINDOW (window);
18318 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18319
18320 eassert (current_buffer == XBUFFER (w->contents));
18321
18322 if (!NILP (Vwindow_scroll_functions))
18323 {
18324 specpdl_ref count = SPECPDL_INDEX ();
18325 specbind (Qinhibit_quit, Qt);
18326 safe_run_hooks_2
18327 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18328 unbind_to (count, Qnil);
18329 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18330
18331 set_buffer_internal (XBUFFER (w->contents));
18332 }
18333
18334 return startp;
18335 }
18336
18337
18338
18339
18340
18341
18342
18343
18344
18345
18346
18347
18348
18349
18350
18351
18352
18353
18354
18355
18356
18357
18358 static bool
18359 cursor_row_fully_visible_p (struct window *w, bool force_p,
18360 bool current_matrix_p,
18361 bool just_test_user_preference_p)
18362 {
18363 struct glyph_matrix *matrix;
18364 struct glyph_row *row;
18365 int window_height;
18366 Lisp_Object mclfv_p =
18367 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18368
18369
18370 if (BASE_EQ (mclfv_p, Qunbound))
18371 mclfv_p = Vmake_cursor_line_fully_visible;
18372
18373
18374 if (FUNCTIONP (mclfv_p))
18375 {
18376 Lisp_Object window;
18377 XSETWINDOW (window, w);
18378
18379
18380 Lisp_Object val = safe_call1 (mclfv_p, window);
18381 if (NILP (val))
18382 return true;
18383 else if (just_test_user_preference_p)
18384 return false;
18385 }
18386 else if (NILP (mclfv_p))
18387 return true;
18388 else if (just_test_user_preference_p)
18389 return false;
18390
18391
18392
18393 if (w->cursor.vpos < 0)
18394 return true;
18395
18396 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18397 row = MATRIX_ROW (matrix, w->cursor.vpos);
18398
18399
18400 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18401 return true;
18402
18403
18404
18405 window_height = window_box_height (w);
18406 if (row->height >= window_height)
18407 {
18408 if (!force_p || MINI_WINDOW_P (w)
18409 || w->vscroll || w->cursor.vpos == 0)
18410 return true;
18411 }
18412 return false;
18413 }
18414
18415
18416
18417
18418
18419
18420
18421
18422
18423
18424
18425
18426
18427
18428
18429
18430
18431
18432
18433
18434 enum
18435 {
18436 SCROLLING_SUCCESS = 1,
18437 SCROLLING_FAILED = 0,
18438 SCROLLING_NEED_LARGER_MATRICES = -1
18439 };
18440
18441
18442
18443
18444
18445 #define SCROLL_LIMIT 100
18446
18447 static int
18448 try_scrolling (Lisp_Object window, bool just_this_one_p,
18449 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18450 bool temp_scroll_step, bool last_line_misfit)
18451 {
18452 struct window *w = XWINDOW (window);
18453 struct text_pos pos, startp;
18454 struct it it;
18455 int this_scroll_margin, scroll_max, rc, height;
18456 int dy = 0, amount_to_scroll = 0;
18457 bool scroll_down_p = false;
18458 int extra_scroll_margin_lines = last_line_misfit;
18459 Lisp_Object aggressive;
18460
18461 int scroll_limit = SCROLL_LIMIT;
18462 int frame_line_height = default_line_pixel_height (w);
18463
18464 #ifdef GLYPH_DEBUG
18465 debug_method_add (w, "try_scrolling");
18466 #endif
18467
18468 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18469
18470 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18471
18472
18473
18474
18475
18476 if (arg_scroll_conservatively > scroll_limit)
18477 {
18478 arg_scroll_conservatively = scroll_limit + 1;
18479 scroll_max = scroll_limit * frame_line_height;
18480 }
18481 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18482
18483
18484 {
18485 intmax_t scroll_lines_max
18486 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18487 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18488 scroll_max = scroll_lines * frame_line_height;
18489 }
18490 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18491 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18492
18493
18494 scroll_max = 10 * frame_line_height;
18495 else
18496 scroll_max = 0;
18497
18498 too_near_end:
18499
18500
18501 if (PT > CHARPOS (startp))
18502 {
18503 int scroll_margin_y;
18504
18505
18506
18507 start_display (&it, w, startp);
18508 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18509 - this_scroll_margin
18510 - frame_line_height * extra_scroll_margin_lines;
18511 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18512 (MOVE_TO_POS | MOVE_TO_Y));
18513
18514 if (PT > CHARPOS (it.current.pos))
18515 {
18516 int y0 = line_bottom_y (&it);
18517
18518
18519
18520
18521
18522 int slack = max (scroll_max, 10 * frame_line_height);
18523 int y_to_move = it.last_visible_y + slack;
18524
18525
18526
18527
18528
18529 move_it_to (&it, PT, -1, y_to_move,
18530 -1, MOVE_TO_POS | MOVE_TO_Y);
18531 dy = line_bottom_y (&it) - y0;
18532
18533 if (dy > scroll_max)
18534 return SCROLLING_FAILED;
18535
18536 if (dy > 0)
18537 scroll_down_p = true;
18538 }
18539 else if (PT == IT_CHARPOS (it)
18540 && IT_CHARPOS (it) < ZV
18541 && it.method == GET_FROM_STRING
18542 && arg_scroll_conservatively > scroll_limit
18543 && it.current_x == 0)
18544 {
18545 enum move_it_result skip;
18546 int y1 = it.current_y;
18547 int vpos;
18548
18549
18550
18551
18552
18553
18554
18555 do {
18556 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18557 if (skip != MOVE_NEWLINE_OR_CR
18558 || IT_CHARPOS (it) != PT
18559 || it.method == GET_FROM_BUFFER)
18560 break;
18561 vpos = it.vpos;
18562 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18563 } while (it.vpos > vpos);
18564
18565 dy = it.current_y - y1;
18566
18567 if (dy > scroll_max)
18568 return SCROLLING_FAILED;
18569
18570 if (dy > 0)
18571 scroll_down_p = true;
18572 }
18573 }
18574
18575 if (scroll_down_p)
18576 {
18577
18578
18579
18580
18581 if (arg_scroll_conservatively)
18582 amount_to_scroll
18583 = min (max (dy, frame_line_height),
18584 frame_line_height * arg_scroll_conservatively);
18585 else if (scroll_step || temp_scroll_step)
18586 amount_to_scroll = scroll_max;
18587 else
18588 {
18589 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18590 height = WINDOW_BOX_TEXT_HEIGHT (w);
18591 if (NUMBERP (aggressive))
18592 {
18593 double float_amount = XFLOATINT (aggressive) * height;
18594 int aggressive_scroll = float_amount;
18595 if (aggressive_scroll == 0 && float_amount > 0)
18596 aggressive_scroll = 1;
18597
18598
18599
18600
18601
18602
18603 if (aggressive_scroll + 2 * this_scroll_margin > height)
18604 aggressive_scroll = height - 2 * this_scroll_margin;
18605 amount_to_scroll = dy + aggressive_scroll;
18606 }
18607 }
18608
18609 if (amount_to_scroll <= 0)
18610 return SCROLLING_FAILED;
18611
18612 start_display (&it, w, startp);
18613 if (arg_scroll_conservatively <= scroll_limit)
18614 move_it_vertically (&it, amount_to_scroll);
18615 else
18616 {
18617
18618
18619
18620
18621
18622
18623 struct it it1;
18624 void *it1data = NULL;
18625
18626
18627 int start_y;
18628
18629 SAVE_IT (it1, it, it1data);
18630 start_y = line_bottom_y (&it1);
18631 do {
18632 RESTORE_IT (&it, &it, it1data);
18633 move_it_by_lines (&it, 1);
18634 SAVE_IT (it1, it, it1data);
18635 } while (IT_CHARPOS (it) < ZV
18636 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18637 bidi_unshelve_cache (it1data, true);
18638 }
18639
18640
18641 if (IT_CHARPOS (it) == CHARPOS (startp))
18642 move_it_by_lines (&it, 1);
18643 startp = it.current.pos;
18644 }
18645 else
18646 {
18647 struct text_pos scroll_margin_pos = startp;
18648 int y_offset = 0;
18649
18650
18651
18652 if (this_scroll_margin)
18653 {
18654 int y_start;
18655
18656 start_display (&it, w, startp);
18657 y_start = it.current_y;
18658 move_it_vertically (&it, this_scroll_margin);
18659 scroll_margin_pos = it.current.pos;
18660
18661
18662
18663 if (IT_CHARPOS (it) == ZV
18664 && it.current_y - y_start < this_scroll_margin)
18665 y_offset = this_scroll_margin - (it.current_y - y_start);
18666 }
18667
18668 if (PT < CHARPOS (scroll_margin_pos))
18669 {
18670
18671
18672 int y0, y_to_move;
18673
18674
18675
18676
18677
18678
18679 SET_TEXT_POS (pos, PT, PT_BYTE);
18680 start_display (&it, w, pos);
18681 y0 = it.current_y;
18682 y_to_move = max (it.last_visible_y,
18683 max (scroll_max, 10 * frame_line_height));
18684 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18685 y_to_move, -1,
18686 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18687 dy = it.current_y - y0;
18688 if (dy > scroll_max
18689 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18690 return SCROLLING_FAILED;
18691
18692
18693 dy += y_offset;
18694
18695
18696 start_display (&it, w, startp);
18697
18698 if (arg_scroll_conservatively)
18699 amount_to_scroll
18700 = min (max (dy, frame_line_height),
18701 frame_line_height * arg_scroll_conservatively);
18702 else if (scroll_step || temp_scroll_step)
18703 amount_to_scroll = scroll_max;
18704 else
18705 {
18706 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18707 height = WINDOW_BOX_TEXT_HEIGHT (w);
18708 if (NUMBERP (aggressive))
18709 {
18710 double float_amount = XFLOATINT (aggressive) * height;
18711 int aggressive_scroll = float_amount;
18712 if (aggressive_scroll == 0 && float_amount > 0)
18713 aggressive_scroll = 1;
18714
18715
18716
18717
18718 if (aggressive_scroll + 2 * this_scroll_margin > height)
18719 aggressive_scroll = height - 2 * this_scroll_margin;
18720 amount_to_scroll = dy + aggressive_scroll;
18721 }
18722 }
18723
18724 if (amount_to_scroll <= 0)
18725 return SCROLLING_FAILED;
18726
18727 move_it_vertically_backward (&it, amount_to_scroll);
18728 startp = it.current.pos;
18729 }
18730 }
18731
18732
18733 startp = run_window_scroll_functions (window, startp);
18734
18735
18736
18737 if (!try_window (window, startp, 0))
18738 rc = SCROLLING_NEED_LARGER_MATRICES;
18739 else if (w->cursor.vpos < 0)
18740 {
18741 clear_glyph_matrix (w->desired_matrix);
18742 rc = SCROLLING_FAILED;
18743 }
18744 else
18745 {
18746
18747 if (!just_this_one_p
18748 || current_buffer->clip_changed
18749 || BEG_UNCHANGED < CHARPOS (startp))
18750 w->base_line_number = 0;
18751
18752
18753
18754 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18755 false, false)
18756
18757
18758
18759 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18760 {
18761 clear_glyph_matrix (w->desired_matrix);
18762 ++extra_scroll_margin_lines;
18763 goto too_near_end;
18764 }
18765 rc = SCROLLING_SUCCESS;
18766 }
18767
18768 return rc;
18769 }
18770
18771
18772
18773
18774
18775
18776
18777
18778
18779
18780
18781
18782 static bool
18783 compute_window_start_on_continuation_line (struct window *w)
18784 {
18785 struct text_pos pos, start_pos, pos_before_pt;
18786 bool window_start_changed_p = false;
18787
18788 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
18789
18790
18791
18792
18793 if (CHARPOS (start_pos) > BEGV
18794 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
18795 {
18796 struct it it;
18797 struct glyph_row *row;
18798
18799
18800 if (CHARPOS (start_pos) < BEGV)
18801 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
18802 else if (CHARPOS (start_pos) > ZV)
18803 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
18804
18805
18806
18807 row = w->desired_matrix->rows + window_wants_tab_line (w)
18808 + window_wants_header_line (w);
18809 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
18810 row, DEFAULT_FACE_ID);
18811 reseat_at_previous_visible_line_start (&it);
18812
18813
18814
18815
18816
18817
18818
18819 if (IT_CHARPOS (it) <= PT
18820 && (CHARPOS (start_pos) - IT_CHARPOS (it)
18821
18822 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
18823 {
18824 int min_distance, distance;
18825
18826
18827
18828
18829
18830
18831
18832 pos_before_pt = pos = it.current.pos;
18833 min_distance = DISP_INFINITY;
18834 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
18835 distance < min_distance)
18836 {
18837 min_distance = distance;
18838 if (CHARPOS (pos) <= PT)
18839 pos_before_pt = pos;
18840 pos = it.current.pos;
18841 if (it.line_wrap == WORD_WRAP)
18842 {
18843
18844
18845
18846
18847
18848
18849
18850
18851
18852 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
18853 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18854 move_it_to (&it, ZV, 0,
18855 it.current_y + it.max_ascent + it.max_descent, -1,
18856 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18857 }
18858 else
18859 move_it_by_lines (&it, 1);
18860 }
18861
18862
18863
18864
18865
18866 if (CHARPOS (pos) > PT)
18867 pos = pos_before_pt;
18868
18869
18870 SET_MARKER_FROM_TEXT_POS (w->start, pos);
18871 window_start_changed_p = true;
18872 }
18873 }
18874
18875 return window_start_changed_p;
18876 }
18877
18878
18879
18880
18881
18882
18883
18884
18885
18886
18887
18888
18889
18890
18891
18892
18893
18894 enum
18895 {
18896 CURSOR_MOVEMENT_SUCCESS,
18897 CURSOR_MOVEMENT_CANNOT_BE_USED,
18898 CURSOR_MOVEMENT_MUST_SCROLL,
18899 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
18900 };
18901
18902 static int
18903 try_cursor_movement (Lisp_Object window, struct text_pos startp,
18904 bool *scroll_step)
18905 {
18906 struct window *w = XWINDOW (window);
18907 struct frame *f = XFRAME (w->frame);
18908 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
18909
18910 #ifdef GLYPH_DEBUG
18911 if (inhibit_try_cursor_movement)
18912 return rc;
18913 #endif
18914
18915
18916
18917
18918 eassert (w->last_point > 0);
18919
18920
18921
18922 eassert (!w->window_end_valid
18923 || w->window_end_vpos < w->current_matrix->nrows);
18924
18925
18926
18927 if (
18928 PT >= CHARPOS (startp)
18929
18930 && !current_buffer->clip_changed
18931
18932
18933
18934
18935 && !update_mode_lines
18936 && !windows_or_buffers_changed
18937 && !f->cursor_type_changed
18938 && NILP (Vshow_trailing_whitespace)
18939
18940
18941 && !EQ (Vdisplay_line_numbers, Qrelative)
18942 && !EQ (Vdisplay_line_numbers, Qvisual)
18943
18944
18945
18946 && !(!NILP (Vdisplay_line_numbers)
18947 && NILP (Finternal_lisp_face_equal_p (Qline_number,
18948 Qline_number_current_line,
18949 w->frame)))
18950
18951
18952
18953
18954
18955
18956 && !EQ (window, minibuf_window)
18957
18958
18959
18960 && !overlay_arrow_in_current_buffer_p ())
18961 {
18962 int this_scroll_margin, top_scroll_margin;
18963 struct glyph_row *row = NULL;
18964
18965 #ifdef GLYPH_DEBUG
18966 debug_method_add (w, "cursor movement");
18967 #endif
18968
18969 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18970
18971 top_scroll_margin = this_scroll_margin;
18972 if (window_wants_tab_line (w))
18973 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
18974 if (window_wants_header_line (w))
18975 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
18976
18977
18978
18979 if (w->last_cursor_vpos < 0
18980 || w->last_cursor_vpos >= w->current_matrix->nrows)
18981 rc = CURSOR_MOVEMENT_MUST_SCROLL;
18982 else
18983 {
18984 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
18985
18986 if (row->tab_line_p)
18987 ++row;
18988 if (row->mode_line_p)
18989 ++row;
18990 if (!row->enabled_p)
18991 rc = CURSOR_MOVEMENT_MUST_SCROLL;
18992 }
18993
18994 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
18995 {
18996 bool scroll_p = false, must_scroll = false;
18997 int last_y = window_text_bottom_y (w) - this_scroll_margin;
18998
18999 if (PT > w->last_point)
19000 {
19001
19002 while (MATRIX_ROW_END_CHARPOS (row) < PT
19003 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19004 {
19005 eassert (row->enabled_p);
19006 ++row;
19007 }
19008
19009
19010
19011
19012 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19013 && MATRIX_ROW_END_CHARPOS (row) == PT
19014 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
19015 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19016 && !cursor_row_p (row))
19017 ++row;
19018
19019
19020
19021
19022
19023 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19024 || PT > MATRIX_ROW_END_CHARPOS (row)
19025
19026
19027 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19028 && PT == MATRIX_ROW_END_CHARPOS (row)
19029 && !row->ends_at_zv_p
19030 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19031 scroll_p = true;
19032 }
19033 else if (PT < w->last_point)
19034 {
19035
19036
19037 struct glyph_row *row0 = row;
19038
19039 while (!row->mode_line_p
19040 && (MATRIX_ROW_START_CHARPOS (row) > PT
19041 || (MATRIX_ROW_START_CHARPOS (row) == PT
19042 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19043 || (
19044 row > w->current_matrix->rows
19045 && (row-1)->ends_in_newline_from_string_p))))
19046 && (row->y > top_scroll_margin
19047 || CHARPOS (startp) == BEGV))
19048 {
19049 eassert (row->enabled_p);
19050 --row;
19051 }
19052
19053
19054
19055
19056
19057 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19058 && PT <= MATRIX_ROW_END_CHARPOS (row))
19059 && row0->continued_p)
19060 {
19061 row = row0;
19062 while (MATRIX_ROW_START_CHARPOS (row) > PT
19063 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19064 {
19065 eassert (row->enabled_p);
19066 ++row;
19067 }
19068 }
19069
19070
19071
19072
19073
19074
19075 if (row < w->current_matrix->rows
19076 || row->mode_line_p)
19077 {
19078 row = w->current_matrix->rows;
19079
19080 if (row->tab_line_p)
19081 ++row;
19082 if (row->mode_line_p)
19083 ++row;
19084 }
19085
19086
19087
19088 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19089 && MATRIX_ROW_END_CHARPOS (row) == PT
19090 && !cursor_row_p (row))
19091 ++row;
19092
19093
19094
19095 if ((row->y < top_scroll_margin
19096 && CHARPOS (startp) != BEGV)
19097 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19098 || PT > MATRIX_ROW_END_CHARPOS (row)
19099 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19100 && PT == MATRIX_ROW_END_CHARPOS (row)
19101 && !row->ends_at_zv_p
19102 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19103 scroll_p = true;
19104 }
19105 else
19106 {
19107
19108
19109 rc = CURSOR_MOVEMENT_SUCCESS;
19110 }
19111
19112 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19113 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19114
19115
19116 || (MATRIX_ROW_END_CHARPOS (row-1)
19117 == MATRIX_ROW_START_CHARPOS (row))))
19118 || PT > MATRIX_ROW_END_CHARPOS (row))
19119 {
19120
19121 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19122 must_scroll = true;
19123 }
19124 else if (rc != CURSOR_MOVEMENT_SUCCESS
19125 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19126 {
19127 struct glyph_row *row1;
19128
19129
19130
19131
19132
19133
19134
19135
19136
19137
19138
19139 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19140 MATRIX_ROW_CONTINUATION_LINE_P (row);
19141 --row)
19142 {
19143
19144
19145
19146 if (row <= row1)
19147 {
19148 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19149 break;
19150 }
19151 eassert (row->enabled_p);
19152 }
19153 }
19154 if (must_scroll)
19155 ;
19156 else if (rc != CURSOR_MOVEMENT_SUCCESS
19157 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19158
19159
19160
19161 && !row->mode_line_p
19162 && !cursor_row_fully_visible_p (w, true, true, true))
19163 {
19164 if (PT == MATRIX_ROW_END_CHARPOS (row)
19165 && !row->ends_at_zv_p
19166 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19167 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19168 else if (row->height > window_box_height (w))
19169 {
19170
19171
19172
19173
19174 *scroll_step = true;
19175 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19176 }
19177 else
19178 {
19179 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19180 if (!cursor_row_fully_visible_p (w, false, true, false))
19181 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19182 else
19183 rc = CURSOR_MOVEMENT_SUCCESS;
19184 }
19185 }
19186 else if (scroll_p)
19187 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19188 else if (rc != CURSOR_MOVEMENT_SUCCESS
19189 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19190 {
19191
19192
19193
19194
19195
19196
19197
19198 bool rv = false;
19199 bool pt_invis = false;
19200 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19201 Qinvisible,
19202 Qnil, NULL);
19203
19204 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19205 pt_invis = true;
19206
19207 do
19208 {
19209 bool at_zv_p = false, exact_match_p = false;
19210
19211
19212
19213
19214
19215 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19216 && PT <= MATRIX_ROW_END_CHARPOS (row)
19217 && cursor_row_p (row))
19218 rv |= set_cursor_from_row (w, row, w->current_matrix,
19219 0, 0, 0, 0);
19220
19221
19222
19223 if (rv)
19224 {
19225 at_zv_p = MATRIX_ROW (w->current_matrix,
19226 w->cursor.vpos)->ends_at_zv_p;
19227 if (!at_zv_p
19228 && w->cursor.hpos >= 0
19229 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19230 w->cursor.vpos))
19231 {
19232 struct glyph_row *candidate =
19233 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19234 struct glyph *g =
19235 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19236 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19237
19238 exact_match_p =
19239 (BUFFERP (g->object) && g->charpos == PT)
19240 || (NILP (g->object)
19241 && (g->charpos == PT
19242 || (g->charpos == 0 && endpos - 1 == PT)));
19243
19244
19245
19246
19247 if (!exact_match_p && pt_invis)
19248 exact_match_p = true;
19249 }
19250 if (at_zv_p || exact_match_p)
19251 {
19252 rc = CURSOR_MOVEMENT_SUCCESS;
19253 break;
19254 }
19255 }
19256 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19257 break;
19258 ++row;
19259 }
19260 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19261 || row->continued_p)
19262 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19263 || (MATRIX_ROW_START_CHARPOS (row) == PT
19264 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19265
19266
19267
19268 if (rc != CURSOR_MOVEMENT_SUCCESS
19269 && !(rv
19270 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19271 && !row->continued_p))
19272 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19273 else if (rv)
19274 rc = CURSOR_MOVEMENT_SUCCESS;
19275 }
19276 else
19277 {
19278 do
19279 {
19280 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19281 {
19282 rc = CURSOR_MOVEMENT_SUCCESS;
19283 break;
19284 }
19285 ++row;
19286 }
19287 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19288 && MATRIX_ROW_START_CHARPOS (row) == PT
19289 && cursor_row_p (row));
19290 }
19291 }
19292 }
19293
19294 return rc;
19295 }
19296
19297
19298 void
19299 set_vertical_scroll_bar (struct window *w)
19300 {
19301 ptrdiff_t start, end, whole;
19302
19303
19304
19305
19306
19307
19308
19309
19310 if (!MINI_WINDOW_P (w)
19311 || (w == XWINDOW (minibuf_window)
19312 && NILP (echo_area_buffer[0])))
19313 {
19314 struct buffer *buf = XBUFFER (w->contents);
19315
19316 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19317 start = marker_position (w->start) - BUF_BEGV (buf);
19318 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19319
19320
19321
19322
19323 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19324 {
19325 struct it it;
19326 struct text_pos start_pos;
19327 struct buffer *obuf = current_buffer;
19328
19329
19330
19331 set_buffer_internal_1 (XBUFFER (w->contents));
19332 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19333 start_display (&it, w, start_pos);
19334 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19335 MOVE_TO_X | MOVE_TO_Y);
19336 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19337 set_buffer_internal_1 (obuf);
19338 }
19339
19340 if (end < start)
19341 end = start;
19342 if (whole < (end - start))
19343 whole = end - start;
19344 }
19345 else
19346 start = end = whole = 0;
19347
19348
19349 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19350 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19351 (w, end - start, whole, start);
19352 }
19353
19354
19355 void
19356 set_horizontal_scroll_bar (struct window *w)
19357 {
19358 int start, end, whole, portion;
19359
19360 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19361 {
19362 struct buffer *b = XBUFFER (w->contents);
19363 struct buffer *old_buffer = NULL;
19364 struct it it;
19365 struct text_pos startp;
19366
19367 if (b != current_buffer)
19368 {
19369 old_buffer = current_buffer;
19370 set_buffer_internal (b);
19371 }
19372
19373 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19374 start_display (&it, w, startp);
19375 it.last_visible_x = INT_MAX;
19376 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19377 MOVE_TO_X | MOVE_TO_Y);
19378
19379
19380
19381
19382 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19383 end = start + window_box_width (w, TEXT_AREA);
19384 portion = end - start;
19385
19386
19387
19388
19389 whole = max (whole, end);
19390
19391 if (it.bidi_p)
19392 {
19393 Lisp_Object pdir;
19394
19395 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19396 if (EQ (pdir, Qright_to_left))
19397 {
19398 start = whole - end;
19399 end = start + portion;
19400 }
19401 }
19402
19403 if (old_buffer)
19404 set_buffer_internal (old_buffer);
19405 }
19406 else
19407 start = end = whole = portion = 0;
19408
19409 w->hscroll_whole = whole;
19410
19411
19412 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19413 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19414 (w, portion, whole, start);
19415 }
19416
19417
19418
19419 static bool
19420 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19421 {
19422 if (!make_window_start_visible)
19423 return true;
19424
19425 struct window *w = XWINDOW (window);
19426 struct frame *f = XFRAME (w->frame);
19427 Lisp_Object startpos = make_fixnum (startp);
19428 Lisp_Object invprop, disp_spec;
19429 struct text_pos ignored;
19430
19431
19432 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19433 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19434 return false;
19435
19436
19437 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19438 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19439 FRAME_WINDOW_P (f)) > 0)
19440 return false;
19441
19442 return true;
19443 }
19444
19445 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19446 0, 0, 0,
19447 doc:
19448
19449 )
19450 (void)
19451 {
19452 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19453 }
19454
19455
19456
19457
19458
19459
19460
19461
19462
19463
19464
19465
19466
19467
19468
19469
19470
19471
19472
19473
19474
19475
19476
19477
19478
19479
19480
19481
19482
19483
19484
19485
19486
19487
19488
19489
19490
19491
19492
19493
19494
19495
19496
19497
19498
19499
19500
19501
19502
19503
19504
19505 static void
19506 redisplay_window (Lisp_Object window, bool just_this_one_p)
19507 {
19508 struct window *w = XWINDOW (window);
19509 struct frame *f = XFRAME (w->frame);
19510 struct buffer *buffer = XBUFFER (w->contents);
19511 struct buffer *old = current_buffer;
19512 struct text_pos lpoint, opoint, startp;
19513 bool update_mode_line;
19514 int tem;
19515 struct it it;
19516
19517 bool current_matrix_up_to_date_p = false;
19518 bool used_current_matrix_p = false;
19519
19520
19521 bool buffer_unchanged_p = false;
19522 bool temp_scroll_step = false;
19523 specpdl_ref count = SPECPDL_INDEX ();
19524 int rc;
19525 int centering_position = -1;
19526 bool last_line_misfit = false;
19527 ptrdiff_t beg_unchanged, end_unchanged;
19528 int frame_line_height, margin;
19529 bool use_desired_matrix;
19530 void *itdata = NULL;
19531
19532 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19533 opoint = lpoint;
19534
19535 #ifdef GLYPH_DEBUG
19536 *w->desired_matrix->method = 0;
19537 #endif
19538
19539 if (!just_this_one_p && needs_no_redisplay (w))
19540 return;
19541
19542
19543 eassert (XMARKER (w->start)->buffer == buffer);
19544 eassert (XMARKER (w->pointm)->buffer == buffer);
19545
19546 reconsider_clip_changes (w);
19547 frame_line_height = default_line_pixel_height (w);
19548 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19549
19550
19551
19552 update_mode_line = (w->update_mode_line
19553 || update_mode_lines
19554 || buffer->clip_changed
19555 || buffer->prevent_redisplay_optimizations_p);
19556
19557 if (!just_this_one_p)
19558
19559
19560 w->must_be_updated_p = true;
19561
19562 if (MINI_WINDOW_P (w))
19563 {
19564 if (w == XWINDOW (echo_area_window)
19565 && !NILP (echo_area_buffer[0]))
19566 {
19567 if (update_mode_line)
19568
19569
19570 goto finish_menu_bars;
19571 else
19572
19573 goto finish_scroll_bars;
19574 }
19575 else if ((w != XWINDOW (minibuf_window)
19576 || minibuf_level == 0)
19577
19578 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19579
19580
19581 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19582 {
19583
19584
19585 int yb = window_text_bottom_y (w);
19586 struct glyph_row *row;
19587 int y;
19588
19589 for (y = 0, row = w->desired_matrix->rows;
19590 y < yb;
19591 y += row->height, ++row)
19592 blank_row (w, row, y);
19593 goto finish_scroll_bars;
19594 }
19595 else if (minibuf_level >= 1)
19596 {
19597
19598
19599
19600 resize_mini_window (w, false);
19601 }
19602
19603 clear_glyph_matrix (w->desired_matrix);
19604 }
19605
19606
19607
19608
19609
19610 set_buffer_internal_1 (XBUFFER (w->contents));
19611
19612 current_matrix_up_to_date_p
19613 = (w->window_end_valid
19614 && !current_buffer->clip_changed
19615 && !current_buffer->prevent_redisplay_optimizations_p
19616 && !window_outdated (w)
19617 && !composition_break_at_point
19618 && !hscrolling_current_line_p (w));
19619
19620 beg_unchanged = BEG_UNCHANGED;
19621 end_unchanged = END_UNCHANGED;
19622
19623 SET_TEXT_POS (opoint, PT, PT_BYTE);
19624
19625 specbind (Qinhibit_point_motion_hooks, Qt);
19626
19627 buffer_unchanged_p
19628 = (w->window_end_valid
19629 && !current_buffer->clip_changed
19630 && !window_outdated (w));
19631
19632
19633
19634 if (windows_or_buffers_changed)
19635 {
19636
19637
19638 if (XMARKER (w->start)->buffer == current_buffer)
19639 compute_window_start_on_continuation_line (w);
19640
19641 w->window_end_valid = false;
19642
19643
19644 current_matrix_up_to_date_p = false;
19645 }
19646
19647
19648 CHECK_WINDOW_END (w);
19649 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19650 emacs_abort ();
19651 if (BYTEPOS (opoint) < CHARPOS (opoint))
19652 emacs_abort ();
19653
19654 if (mode_line_update_needed (w))
19655 update_mode_line = true;
19656
19657
19658
19659 if (!EQ (window, selected_window))
19660 {
19661 ptrdiff_t new_pt = marker_position (w->pointm);
19662 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19663
19664 if (new_pt < BEGV)
19665 {
19666 new_pt = BEGV;
19667 new_pt_byte = BEGV_BYTE;
19668 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19669 }
19670 else if (new_pt > (ZV - 1))
19671 {
19672 new_pt = ZV;
19673 new_pt_byte = ZV_BYTE;
19674 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19675 }
19676
19677
19678 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19679 }
19680
19681
19682
19683
19684
19685
19686 if (current_buffer->width_run_cache
19687 || (current_buffer->base_buffer
19688 && current_buffer->base_buffer->width_run_cache))
19689 {
19690 struct Lisp_Char_Table *disptab = buffer_display_table ();
19691
19692 if (! disptab_matches_widthtab
19693 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19694 {
19695 struct buffer *buf = current_buffer;
19696
19697 if (buf->base_buffer)
19698 buf = buf->base_buffer;
19699 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19700 recompute_width_table (current_buffer, disptab);
19701 }
19702 }
19703
19704
19705 if (!NILP (Vlong_line_threshold)
19706 && !current_buffer->long_line_optimizations_p
19707 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19708 || current_buffer->clip_changed))
19709 {
19710 ptrdiff_t cur, next, found, max = 0, threshold;
19711 threshold = XFIXNUM (Vlong_line_threshold);
19712 for (cur = BEGV; cur < ZV; cur = next)
19713 {
19714 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19715 &found, NULL, true);
19716 if (next - cur > max) max = next - cur;
19717 if (!found || max > threshold) break;
19718 }
19719 if (max > threshold)
19720 current_buffer->long_line_optimizations_p = true;
19721 }
19722
19723
19724 if (XMARKER (w->start)->buffer != current_buffer)
19725 goto recenter;
19726
19727 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19728
19729
19730
19731 if ((w->optional_new_start || window_frozen_p (w))
19732 && CHARPOS (startp) >= BEGV
19733 && CHARPOS (startp) <= ZV)
19734 {
19735 ptrdiff_t it_charpos;
19736
19737 w->optional_new_start = false;
19738 if (!w->force_start)
19739 {
19740 start_display (&it, w, startp);
19741 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19742 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19743
19744
19745 it_charpos = IT_CHARPOS (it);
19746
19747
19748
19749
19750
19751 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19752 {
19753 if (it_charpos == PT)
19754 w->force_start = true;
19755
19756 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19757 w->force_start = true;
19758 #ifdef GLYPH_DEBUG
19759 if (w->force_start)
19760 {
19761 if (window_frozen_p (w))
19762 debug_method_add (w, "set force_start from frozen window start");
19763 else
19764 debug_method_add (w, "set force_start from optional_new_start");
19765 }
19766 #endif
19767 }
19768 }
19769 }
19770
19771 force_start:
19772
19773
19774
19775 if (w->force_start)
19776 {
19777
19778 int new_vpos = -1;
19779
19780 w->force_start = false;
19781
19782
19783
19784
19785 if (!w->preserve_vscroll_p || !window_frozen_p (w))
19786 w->vscroll = 0;
19787
19788 w->preserve_vscroll_p = false;
19789 w->window_end_valid = false;
19790
19791
19792 if (!buffer_unchanged_p)
19793 w->base_line_number = 0;
19794
19795
19796
19797
19798
19799
19800
19801
19802 if (!update_mode_line
19803 || ! NILP (Vwindow_scroll_functions))
19804 {
19805 update_mode_line = true;
19806 w->update_mode_line = true;
19807 startp = run_window_scroll_functions (window, startp);
19808 }
19809
19810 if (CHARPOS (startp) < BEGV)
19811 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
19812 else if (CHARPOS (startp) > ZV)
19813 SET_TEXT_POS (startp, ZV, ZV_BYTE);
19814
19815
19816
19817 if (!window_start_acceptable_p (window, CHARPOS (startp)))
19818 goto ignore_start;
19819
19820
19821
19822
19823
19824
19825 clear_glyph_matrix (w->desired_matrix);
19826 if (!try_window (window, startp, 0))
19827 {
19828 w->force_start = true;
19829 clear_glyph_matrix (w->desired_matrix);
19830 goto need_larger_matrices;
19831 }
19832
19833 if (w->cursor.vpos < 0)
19834 {
19835
19836
19837
19838
19839
19840 struct glyph_row *r = NULL;
19841 Lisp_Object invprop =
19842 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
19843 Qnil, NULL);
19844
19845 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19846 {
19847 ptrdiff_t alt_pt;
19848 Lisp_Object invprop_end =
19849 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
19850 Qnil, Qnil);
19851
19852 if (FIXNATP (invprop_end))
19853 alt_pt = XFIXNAT (invprop_end);
19854 else
19855 alt_pt = ZV;
19856 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
19857 NULL, 0);
19858 }
19859 if (r)
19860 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
19861 else
19862 new_vpos = window_box_height (w) / 2;
19863 }
19864
19865 if (!cursor_row_fully_visible_p (w, false, false, false))
19866 {
19867
19868
19869 new_vpos = window_box_height (w);
19870
19871
19872
19873
19874
19875
19876 if (new_vpos >= w->cursor.y)
19877 {
19878 w->cursor.vpos = -1;
19879 clear_glyph_matrix (w->desired_matrix);
19880 goto try_to_scroll;
19881 }
19882 }
19883 else if (w->cursor.vpos >= 0)
19884 {
19885
19886
19887
19888 int pixel_margin = margin * frame_line_height;
19889 bool tab_line = window_wants_tab_line (w);
19890 bool header_line = window_wants_header_line (w);
19891
19892
19893
19894
19895
19896 if (w->cursor.vpos < margin + tab_line + header_line)
19897 {
19898 w->cursor.vpos = -1;
19899 clear_glyph_matrix (w->desired_matrix);
19900 goto try_to_scroll;
19901 }
19902 else
19903 {
19904 int window_height = window_box_height (w);
19905
19906 if (tab_line)
19907 window_height += CURRENT_TAB_LINE_HEIGHT (w);
19908 if (header_line)
19909 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
19910 if (w->cursor.y >= window_height - pixel_margin)
19911 {
19912 w->cursor.vpos = -1;
19913 clear_glyph_matrix (w->desired_matrix);
19914 goto try_to_scroll;
19915 }
19916 }
19917 }
19918
19919
19920
19921 if (new_vpos >= 0)
19922 {
19923 struct glyph_row *row;
19924
19925 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
19926 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
19927 && !row->ends_at_zv_p)
19928 ++row;
19929
19930 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
19931 MATRIX_ROW_START_BYTEPOS (row));
19932
19933 if (w != XWINDOW (selected_window))
19934 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
19935 else if (current_buffer == old)
19936 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19937
19938 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
19939
19940
19941
19942
19943
19944
19945
19946 w->redisplay = false;
19947 XBUFFER (w->contents)->text->redisplay = false;
19948 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
19949
19950 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
19951 || ((EQ (Vdisplay_line_numbers, Qrelative)
19952 || EQ (Vdisplay_line_numbers, Qvisual))
19953 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
19954 {
19955
19956
19957
19958
19959 clear_glyph_matrix (w->desired_matrix);
19960 if (!try_window (window, startp, 0))
19961 goto need_larger_matrices;
19962 }
19963 }
19964 if (w->cursor.vpos < 0
19965 || !cursor_row_fully_visible_p (w, false, false, false))
19966 {
19967 clear_glyph_matrix (w->desired_matrix);
19968 goto try_to_scroll;
19969 }
19970
19971 #ifdef GLYPH_DEBUG
19972 debug_method_add (w, "forced window start");
19973 #endif
19974 goto done;
19975 }
19976
19977 ignore_start:
19978
19979
19980
19981
19982 if (current_matrix_up_to_date_p
19983 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
19984 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
19985 {
19986 switch (rc)
19987 {
19988 case CURSOR_MOVEMENT_SUCCESS:
19989 used_current_matrix_p = true;
19990 goto done;
19991
19992 case CURSOR_MOVEMENT_MUST_SCROLL:
19993 goto try_to_scroll;
19994
19995 default:
19996 emacs_abort ();
19997 }
19998 }
19999
20000
20001
20002 else if (w->start_at_line_beg
20003 && ((CHARPOS (startp) > BEGV
20004 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
20005 || (CHARPOS (startp) >= BEGV
20006 && CHARPOS (startp) <= ZV
20007 && !window_start_acceptable_p (window, CHARPOS (startp)))))
20008 {
20009 #ifdef GLYPH_DEBUG
20010 debug_method_add (w, "recenter 1");
20011 #endif
20012 goto recenter;
20013 }
20014
20015
20016
20017
20018 else if ((tem = try_window_id (w)) != 0)
20019 {
20020 #ifdef GLYPH_DEBUG
20021 debug_method_add (w, "try_window_id %d", tem);
20022 #endif
20023
20024 if (f->fonts_changed)
20025 goto need_larger_matrices;
20026 if (tem > 0)
20027 goto done;
20028
20029
20030
20031 }
20032 else if (CHARPOS (startp) >= BEGV
20033 && CHARPOS (startp) <= ZV
20034 && PT >= CHARPOS (startp)
20035 && (CHARPOS (startp) < ZV
20036
20037 || CHARPOS (startp) == BEGV
20038 || !window_outdated (w)))
20039 {
20040 int d1, d2, d5, d6;
20041 int rtop, rbot;
20042
20043
20044
20045
20046
20047
20048
20049
20050
20051
20052 if (!w->start_at_line_beg
20053 && NILP (track_mouse)
20054 && CHARPOS (startp) > BEGV
20055 && CHARPOS (startp) > BEG + beg_unchanged
20056 && CHARPOS (startp) <= Z - end_unchanged
20057
20058
20059
20060
20061
20062 && XMARKER (w->start)->buffer == current_buffer
20063 && compute_window_start_on_continuation_line (w)
20064
20065
20066
20067
20068
20069
20070 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20071
20072
20073 && (rtop != 0) == (rbot != 0))
20074 {
20075 w->force_start = true;
20076 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20077 #ifdef GLYPH_DEBUG
20078 debug_method_add (w, "recomputed window start in continuation line");
20079 #endif
20080 goto force_start;
20081 }
20082
20083
20084
20085
20086 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20087 {
20088 #ifdef GLYPH_DEBUG
20089 debug_method_add (w, "recenter 2");
20090 #endif
20091 goto recenter;
20092 }
20093
20094 #ifdef GLYPH_DEBUG
20095 debug_method_add (w, "same window start");
20096 #endif
20097
20098
20099
20100 if (!current_matrix_up_to_date_p
20101
20102
20103
20104 || !NILP (Vwindow_scroll_functions)
20105 || MINI_WINDOW_P (w)
20106 || !(used_current_matrix_p
20107 = try_window_reusing_current_matrix (w)))
20108 {
20109 IF_DEBUG (debug_method_add (w, "1"));
20110 clear_glyph_matrix (w->desired_matrix);
20111 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20112
20113
20114
20115 goto try_to_scroll;
20116 }
20117
20118 if (f->fonts_changed)
20119 goto need_larger_matrices;
20120
20121 if (w->cursor.vpos >= 0)
20122 {
20123 if (!just_this_one_p
20124 || current_buffer->clip_changed
20125 || BEG_UNCHANGED < CHARPOS (startp))
20126
20127 w->base_line_number = 0;
20128
20129 if (!cursor_row_fully_visible_p (w, true, false, false))
20130 {
20131 clear_glyph_matrix (w->desired_matrix);
20132 last_line_misfit = true;
20133 }
20134
20135 else
20136 goto done;
20137 }
20138 else
20139 clear_glyph_matrix (w->desired_matrix);
20140 }
20141
20142 try_to_scroll:
20143
20144
20145 if (!update_mode_line)
20146 {
20147 update_mode_line = true;
20148 w->update_mode_line = true;
20149 }
20150
20151
20152 if ((0 < scroll_conservatively
20153
20154
20155
20156
20157 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20158 || 0 < emacs_scroll_step
20159 || temp_scroll_step
20160 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20161 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20162 && CHARPOS (startp) >= BEGV
20163 && CHARPOS (startp) <= ZV)
20164 {
20165
20166
20167 int ss = try_scrolling (window, just_this_one_p,
20168 ((scroll_minibuffer_conservatively
20169 && MINI_WINDOW_P (w))
20170 ? SCROLL_LIMIT + 1
20171 : scroll_conservatively),
20172 emacs_scroll_step,
20173 temp_scroll_step, last_line_misfit);
20174 switch (ss)
20175 {
20176 case SCROLLING_SUCCESS:
20177 goto done;
20178
20179 case SCROLLING_NEED_LARGER_MATRICES:
20180 goto need_larger_matrices;
20181
20182 case SCROLLING_FAILED:
20183 break;
20184
20185 default:
20186 emacs_abort ();
20187 }
20188 }
20189
20190
20191
20192
20193 recenter:
20194
20195 #ifdef GLYPH_DEBUG
20196 debug_method_add (w, "recenter");
20197 #endif
20198
20199
20200 if (!buffer_unchanged_p)
20201 w->base_line_number = 0;
20202
20203
20204 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20205 it.current_y = it.last_visible_y;
20206 if (centering_position < 0)
20207 {
20208 ptrdiff_t margin_pos = CHARPOS (startp);
20209 Lisp_Object aggressive;
20210 bool scrolling_up;
20211
20212
20213
20214 if (margin
20215
20216
20217
20218
20219
20220
20221 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20222 {
20223 struct it it1;
20224 void *it1data = NULL;
20225
20226 SAVE_IT (it1, it, it1data);
20227 start_display (&it1, w, startp);
20228 move_it_vertically (&it1, margin * frame_line_height);
20229 margin_pos = IT_CHARPOS (it1);
20230 RESTORE_IT (&it, &it, it1data);
20231 }
20232 scrolling_up = PT > margin_pos;
20233 aggressive =
20234 scrolling_up
20235 ? BVAR (current_buffer, scroll_up_aggressively)
20236 : BVAR (current_buffer, scroll_down_aggressively);
20237
20238 if (!MINI_WINDOW_P (w)
20239 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20240 {
20241 int pt_offset = 0;
20242
20243
20244
20245 if (!scroll_conservatively && NUMBERP (aggressive))
20246 {
20247 double float_amount = XFLOATINT (aggressive);
20248
20249 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20250 if (pt_offset == 0 && float_amount > 0)
20251 pt_offset = 1;
20252 if (pt_offset && margin > 0)
20253 margin -= 1;
20254 }
20255
20256
20257
20258 if (scrolling_up)
20259 {
20260 centering_position = it.last_visible_y;
20261 if (pt_offset)
20262 centering_position -= pt_offset;
20263 centering_position -=
20264 (frame_line_height * (1 + margin + last_line_misfit)
20265 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20266
20267
20268 if (centering_position < margin * frame_line_height)
20269 centering_position = margin * frame_line_height;
20270 }
20271 else
20272 centering_position = margin * frame_line_height + pt_offset;
20273 }
20274 else
20275
20276
20277 centering_position = window_box_height (w) / 2;
20278 }
20279 if (current_buffer->long_line_optimizations_p
20280 && it.line_wrap == TRUNCATE)
20281 {
20282
20283
20284
20285 int nlines = centering_position / frame_line_height;
20286
20287 while (nlines-- && IT_CHARPOS (it) > BEGV)
20288 back_to_previous_visible_line_start (&it);
20289 reseat_1 (&it, it.current.pos, true);
20290 }
20291 else
20292 move_it_vertically_backward (&it, centering_position);
20293
20294 eassert (IT_CHARPOS (it) >= BEGV);
20295
20296
20297
20298
20299
20300
20301 if (it.current_y <= 0)
20302 {
20303 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20304 move_it_vertically_backward (&it, 0);
20305 it.current_y = 0;
20306 }
20307
20308 it.current_x = it.hpos = 0;
20309
20310
20311
20312
20313 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20314
20315
20316 startp = run_window_scroll_functions (window, it.current.pos);
20317
20318
20319
20320
20321 itdata = bidi_shelve_cache ();
20322
20323
20324 use_desired_matrix = false;
20325 if (!current_matrix_up_to_date_p
20326 || windows_or_buffers_changed
20327 || f->cursor_type_changed
20328
20329
20330 || !NILP (Vwindow_scroll_functions)
20331 || !just_this_one_p
20332 || MINI_WINDOW_P (w)
20333 || !(used_current_matrix_p
20334 = try_window_reusing_current_matrix (w)))
20335 use_desired_matrix = (try_window (window, startp, 0) == 1);
20336
20337 bidi_unshelve_cache (itdata, false);
20338
20339
20340
20341
20342 if (f->fonts_changed)
20343 goto need_larger_matrices;
20344
20345
20346
20347
20348
20349
20350 if (w->cursor.vpos < 0)
20351 {
20352 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20353 {
20354 clear_glyph_matrix (w->desired_matrix);
20355 move_it_by_lines (&it, 1);
20356 try_window (window, it.current.pos, 0);
20357 }
20358 else if (PT < IT_CHARPOS (it))
20359 {
20360 clear_glyph_matrix (w->desired_matrix);
20361 move_it_by_lines (&it, -1);
20362 try_window (window, it.current.pos, 0);
20363 }
20364 else if (scroll_conservatively > SCROLL_LIMIT
20365 && (it.method == GET_FROM_STRING
20366 || overlay_touches_p (IT_CHARPOS (it)))
20367 && IT_CHARPOS (it) < ZV)
20368 {
20369
20370
20371
20372
20373
20374
20375
20376
20377 ptrdiff_t pos0 = IT_CHARPOS (it);
20378
20379 clear_glyph_matrix (w->desired_matrix);
20380 do {
20381 move_it_by_lines (&it, 1);
20382 } while (IT_CHARPOS (it) == pos0);
20383 try_window (window, it.current.pos, 0);
20384 }
20385 else
20386 {
20387
20388 }
20389 }
20390
20391
20392
20393
20394
20395
20396 if (w->cursor.vpos < 0)
20397 {
20398
20399
20400
20401
20402 struct glyph_matrix *matrix =
20403 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20404
20405 struct glyph_row *row =
20406 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20407
20408
20409
20410
20411
20412
20413
20414 if (!row)
20415 {
20416 Lisp_Object val =
20417 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20418 Qnil, NULL);
20419
20420 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20421 {
20422 ptrdiff_t alt_pos;
20423 Lisp_Object invis_end =
20424 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20425 Qnil, Qnil);
20426
20427 if (FIXNATP (invis_end))
20428 alt_pos = XFIXNAT (invis_end);
20429 else
20430 alt_pos = ZV;
20431 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20432 }
20433 }
20434
20435
20436
20437 if (!row)
20438 {
20439 row = matrix->rows;
20440
20441 if (row->tab_line_p)
20442 ++row;
20443 if (row->mode_line_p)
20444 ++row;
20445 }
20446 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20447 }
20448
20449 if (!cursor_row_fully_visible_p (w, false, false, false))
20450 {
20451
20452 if (w->vscroll)
20453 {
20454 w->vscroll = 0;
20455 clear_glyph_matrix (w->desired_matrix);
20456 goto recenter;
20457 }
20458
20459
20460
20461
20462
20463 if (scroll_conservatively > SCROLL_LIMIT)
20464 {
20465 int window_total_lines
20466 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20467 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20468
20469 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20470 clear_glyph_matrix (w->desired_matrix);
20471 if (1 == try_window (window, it.current.pos,
20472 TRY_WINDOW_CHECK_MARGINS))
20473 goto done;
20474 }
20475
20476
20477
20478
20479 if (centering_position == 0)
20480 goto done;
20481
20482 clear_glyph_matrix (w->desired_matrix);
20483 centering_position = 0;
20484 goto recenter;
20485 }
20486
20487 done:
20488
20489 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20490 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20491 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20492
20493
20494 if ((update_mode_line
20495
20496
20497
20498
20499 || (!just_this_one_p
20500 && !FRAME_WINDOW_P (f)
20501 && !WINDOW_FULL_WIDTH_P (w))
20502
20503 || w->base_line_pos > 0
20504
20505 || (w->column_number_displayed != -1
20506 && (w->column_number_displayed != current_column ())))
20507
20508 && (window_wants_mode_line (w)
20509 || window_wants_header_line (w)
20510 || window_wants_tab_line (w)))
20511 {
20512 specpdl_ref count1 = SPECPDL_INDEX ();
20513
20514 specbind (Qinhibit_quit, Qt);
20515 display_mode_lines (w);
20516 unbind_to (count1, Qnil);
20517
20518
20519
20520 if (window_wants_mode_line (w)
20521 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20522 {
20523 f->fonts_changed = true;
20524 w->mode_line_height = -1;
20525 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20526 = DESIRED_MODE_LINE_HEIGHT (w);
20527 }
20528
20529
20530
20531 if (window_wants_tab_line (w)
20532 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20533 {
20534 f->fonts_changed = true;
20535 w->tab_line_height = -1;
20536 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20537 = DESIRED_TAB_LINE_HEIGHT (w);
20538 }
20539
20540
20541
20542 if (window_wants_header_line (w)
20543 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20544 {
20545 f->fonts_changed = true;
20546 w->header_line_height = -1;
20547 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20548 = DESIRED_HEADER_LINE_HEIGHT (w);
20549 }
20550
20551 if (f->fonts_changed)
20552 goto need_larger_matrices;
20553 }
20554
20555 if (!line_number_displayed && w->base_line_pos != -1)
20556 {
20557 w->base_line_pos = 0;
20558 w->base_line_number = 0;
20559 }
20560
20561 finish_menu_bars:
20562
20563
20564
20565 if (update_mode_line
20566 && EQ (FRAME_SELECTED_WINDOW (f), window))
20567 {
20568 bool redisplay_menu_p;
20569
20570 if (FRAME_WINDOW_P (f))
20571 {
20572 #ifdef HAVE_EXT_MENU_BAR
20573 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20574 #else
20575 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20576 #endif
20577 }
20578 else
20579 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20580
20581 if (redisplay_menu_p)
20582 display_menu_bar (w);
20583
20584 #ifdef HAVE_WINDOW_SYSTEM
20585 if (FRAME_WINDOW_P (f))
20586 {
20587 if (WINDOWP (f->tab_bar_window)
20588 && (FRAME_TAB_BAR_LINES (f) > 0
20589 || !NILP (Vauto_resize_tab_bars))
20590 && redisplay_tab_bar (f))
20591 ignore_mouse_drag_p = true;
20592
20593 #ifdef HAVE_EXT_TOOL_BAR
20594 if (FRAME_EXTERNAL_TOOL_BAR (f))
20595 update_frame_tool_bar (f);
20596 #else
20597 if (WINDOWP (f->tool_bar_window)
20598 && (FRAME_TOOL_BAR_LINES (f) > 0
20599 || !NILP (Vauto_resize_tool_bars))
20600 && redisplay_tool_bar (f))
20601 ignore_mouse_drag_p = true;
20602 #endif
20603 }
20604 else
20605 {
20606 if ((FRAME_TAB_BAR_LINES (f) > 0))
20607 display_tab_bar (w);
20608 }
20609
20610 gui_consider_frame_title (w->frame);
20611 #else
20612 if ((FRAME_TAB_BAR_LINES (f) > 0))
20613 display_tab_bar (w);
20614 #endif
20615 }
20616
20617 #ifdef HAVE_WINDOW_SYSTEM
20618 if (FRAME_WINDOW_P (f)
20619 && update_window_fringes (w, (just_this_one_p
20620 || (!used_current_matrix_p && !overlay_arrow_seen)
20621 || w->pseudo_window_p)))
20622 {
20623 update_begin (f);
20624 block_input ();
20625 if (draw_window_fringes (w, true))
20626 {
20627 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20628 gui_draw_right_divider (w);
20629 else
20630 gui_draw_vertical_border (w);
20631 }
20632 unblock_input ();
20633 update_end (f);
20634 }
20635
20636 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20637 gui_draw_bottom_divider (w);
20638 #endif
20639
20640
20641
20642
20643
20644 need_larger_matrices:
20645 ;
20646 finish_scroll_bars:
20647
20648 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20649 {
20650 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20651
20652 set_vertical_scroll_bar (w);
20653
20654 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20655
20656 set_horizontal_scroll_bar (w);
20657
20658
20659
20660 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20661 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20662 }
20663
20664
20665
20666
20667 if (CHARPOS (opoint) < BEGV)
20668 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20669 else if (CHARPOS (opoint) > ZV)
20670 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20671 else
20672 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20673
20674 set_buffer_internal_1 (old);
20675
20676
20677 if (CHARPOS (lpoint) <= ZV)
20678 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20679
20680 unbind_to (count, Qnil);
20681 }
20682
20683
20684
20685
20686
20687
20688
20689
20690
20691
20692
20693
20694
20695
20696
20697
20698
20699
20700
20701
20702 int
20703 try_window (Lisp_Object window, struct text_pos pos, int flags)
20704 {
20705 struct window *w = XWINDOW (window);
20706 struct it it;
20707 struct glyph_row *last_text_row = NULL;
20708 struct frame *f = XFRAME (w->frame);
20709 int cursor_vpos = w->cursor.vpos;
20710
20711
20712 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20713
20714
20715 w->cursor.vpos = -1;
20716 overlay_arrow_seen = false;
20717
20718
20719 start_display (&it, w, pos);
20720 it.glyph_row->reversed_p = false;
20721
20722
20723 while (it.current_y < it.last_visible_y)
20724 {
20725 int last_row_scale = it.w->nrows_scale_factor;
20726 int last_col_scale = it.w->ncols_scale_factor;
20727 if (display_line (&it, cursor_vpos))
20728 last_text_row = it.glyph_row - 1;
20729 if (f->fonts_changed
20730 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20731
20732
20733 && last_row_scale == it.w->nrows_scale_factor
20734 && last_col_scale == it.w->ncols_scale_factor))
20735 return 0;
20736 }
20737
20738
20739
20740 ptrdiff_t it_charpos = IT_CHARPOS (it);
20741
20742
20743
20744
20745 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20746 && w->vscroll == 0
20747 && !MINI_WINDOW_P (w))
20748 {
20749 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20750 int bot_scroll_margin = top_scroll_margin;
20751 if (window_wants_header_line (w))
20752 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20753 if (window_wants_tab_line (w))
20754 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20755 start_display (&it, w, pos);
20756
20757 if ((w->cursor.y >= 0
20758 && w->cursor.y < top_scroll_margin
20759 && CHARPOS (pos) > BEGV)
20760
20761
20762
20763
20764 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20765 - bot_scroll_margin - 1))
20766 {
20767 w->cursor.vpos = -1;
20768 clear_glyph_matrix (w->desired_matrix);
20769 return -1;
20770 }
20771 }
20772
20773
20774 if (w->window_end_pos <= 0 && Z != it_charpos)
20775 w->update_mode_line = true;
20776
20777
20778
20779
20780 if (last_text_row)
20781 {
20782 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
20783 adjust_window_ends (w, last_text_row, false);
20784 eassert
20785 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
20786 w->window_end_vpos)));
20787 }
20788 else
20789 {
20790 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
20791 w->window_end_pos = Z - ZV;
20792 w->window_end_vpos = 0;
20793 }
20794
20795
20796 w->window_end_valid = false;
20797 return 1;
20798 }
20799
20800
20801
20802
20803
20804
20805
20806
20807
20808
20809
20810
20811 static bool
20812 try_window_reusing_current_matrix (struct window *w)
20813 {
20814 struct frame *f = XFRAME (w->frame);
20815 struct glyph_row *bottom_row;
20816 struct it it;
20817 struct run run;
20818 struct text_pos start, new_start;
20819 int nrows_scrolled, i;
20820 struct glyph_row *last_text_row;
20821 struct glyph_row *last_reused_text_row;
20822 struct glyph_row *start_row;
20823 int start_vpos, min_y, max_y;
20824
20825 #ifdef GLYPH_DEBUG
20826 if (inhibit_try_window_reusing)
20827 return false;
20828 #endif
20829
20830 if (
20831 !FRAME_WINDOW_P (f)
20832
20833
20834 || windows_or_buffers_changed
20835 || f->cursor_type_changed
20836
20837
20838
20839 || overlay_arrow_in_current_buffer_p ())
20840 return false;
20841
20842
20843 if (!NILP (Vshow_trailing_whitespace))
20844 return false;
20845
20846
20847 if (window_wants_tab_line (w)
20848 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
20849 return false;
20850
20851
20852 if (window_wants_header_line (w)
20853 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
20854 return false;
20855
20856
20857
20858 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20859 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
20860 return false;
20861
20862
20863 clear_glyph_matrix (w->desired_matrix);
20864
20865
20866
20867
20868 if (!NILP (Vdisplay_line_numbers))
20869 return false;
20870
20871
20872
20873
20874 #ifdef HAVE_NTGUI
20875 if (w32_use_visible_system_caret)
20876 return false;
20877 #endif
20878
20879
20880
20881 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
20882 start = start_row->minpos;
20883 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
20884
20885 if (CHARPOS (new_start) <= CHARPOS (start))
20886 {
20887
20888
20889
20890
20891 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
20892 return false;
20893
20894 IF_DEBUG (debug_method_add (w, "twu1"));
20895
20896
20897
20898
20899
20900 start_display (&it, w, new_start);
20901 w->cursor.vpos = -1;
20902 last_text_row = last_reused_text_row = NULL;
20903
20904 while (it.current_y < it.last_visible_y && !f->fonts_changed)
20905 {
20906
20907
20908
20909
20910 while (IT_CHARPOS (it) > CHARPOS (start))
20911 {
20912
20913 start_row++;
20914 start = start_row->minpos;
20915
20916 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
20917 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
20918 || CHARPOS (start) == ZV)
20919 {
20920 clear_glyph_matrix (w->desired_matrix);
20921 return false;
20922 }
20923
20924 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
20925 }
20926
20927
20928 if (IT_CHARPOS (it) == CHARPOS (start)
20929
20930
20931
20932
20933
20934 && it.current.dpvec_index < 0)
20935 break;
20936
20937 it.glyph_row->reversed_p = false;
20938 if (display_line (&it, -1))
20939 last_text_row = it.glyph_row - 1;
20940
20941 }
20942
20943
20944
20945
20946 if (it.current_y < it.last_visible_y)
20947 {
20948 struct glyph_row *row;
20949
20950
20951 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
20952
20953
20954 if (w->cursor.vpos < 0)
20955 {
20956 int dy = it.current_y - start_row->y;
20957
20958 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20959 row = row_containing_pos (w, PT, row, NULL, dy);
20960 if (row)
20961 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
20962 dy, nrows_scrolled);
20963 else
20964 {
20965 clear_glyph_matrix (w->desired_matrix);
20966 return false;
20967 }
20968 }
20969
20970
20971
20972
20973
20974
20975
20976 run.current_y = start_row->y;
20977 run.desired_y = it.current_y;
20978 run.height = it.last_visible_y - it.current_y;
20979
20980 if (run.height > 0 && run.current_y != run.desired_y)
20981 {
20982 #ifdef HAVE_WINDOW_SYSTEM
20983 update_begin (f);
20984 gui_update_window_begin (w);
20985 FRAME_RIF (f)->clear_window_mouse_face (w);
20986 FRAME_RIF (f)->scroll_run_hook (w, &run);
20987 gui_update_window_end (w, false, false);
20988 update_end (f);
20989 #endif
20990 }
20991
20992
20993 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
20994 rotate_matrix (w->current_matrix,
20995 start_vpos,
20996 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
20997 nrows_scrolled);
20998
20999
21000 for (i = 0; i < nrows_scrolled; ++i)
21001 (start_row + i)->enabled_p = false;
21002
21003
21004 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21005 max_y = it.last_visible_y;
21006 for (row = start_row + nrows_scrolled;
21007 row < bottom_row;
21008 ++row)
21009 {
21010 row->y = it.current_y;
21011 row->visible_height = row->height;
21012
21013 if (row->y < min_y)
21014 row->visible_height -= min_y - row->y;
21015 if (row->y + row->height > max_y)
21016 row->visible_height -= row->y + row->height - max_y;
21017 if (row->fringe_bitmap_periodic_p)
21018 row->redraw_fringe_bitmaps_p = true;
21019
21020 it.current_y += row->height;
21021
21022 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21023 last_reused_text_row = row;
21024 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21025 break;
21026 }
21027
21028
21029
21030 for (++row; row < bottom_row; ++row)
21031 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21032 }
21033
21034
21035
21036
21037
21038 if (last_reused_text_row)
21039 adjust_window_ends (w, last_reused_text_row, true);
21040 else if (last_text_row)
21041 adjust_window_ends (w, last_text_row, false);
21042 else
21043 {
21044
21045 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21046 w->window_end_pos = Z - ZV;
21047 w->window_end_vpos = 0;
21048 }
21049 w->window_end_valid = false;
21050
21051
21052 w->desired_matrix->no_scrolling_p = true;
21053
21054 #ifdef GLYPH_DEBUG
21055 debug_method_add (w, "try_window_reusing_current_matrix 1");
21056 #endif
21057 return true;
21058 }
21059 else if (CHARPOS (new_start) > CHARPOS (start))
21060 {
21061 struct glyph_row *pt_row, *row;
21062 struct glyph_row *first_reusable_row;
21063 struct glyph_row *first_row_to_display;
21064 int dy;
21065 int yb = window_text_bottom_y (w);
21066
21067
21068
21069 first_reusable_row = start_row;
21070 while (first_reusable_row->enabled_p
21071 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21072 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21073 < CHARPOS (new_start)))
21074 ++first_reusable_row;
21075
21076
21077 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21078 || !first_reusable_row->enabled_p
21079 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21080 != CHARPOS (new_start)))
21081 return false;
21082
21083
21084
21085
21086
21087 pt_row = NULL;
21088 for (first_row_to_display = first_reusable_row;
21089 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21090 ++first_row_to_display)
21091 {
21092 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21093 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21094 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21095 && first_row_to_display->ends_at_zv_p
21096 && pt_row == NULL)))
21097 pt_row = first_row_to_display;
21098 }
21099
21100 if (first_row_to_display->y >= yb)
21101 return false;
21102
21103
21104 init_to_row_start (&it, w, first_row_to_display);
21105
21106 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21107 - start_vpos);
21108 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21109 - nrows_scrolled);
21110 it.current_y = (first_row_to_display->y - first_reusable_row->y
21111 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21112
21113
21114
21115
21116 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21117 if (pt_row == NULL)
21118 w->cursor.vpos = -1;
21119 last_text_row = NULL;
21120 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21121 if (display_line (&it, w->cursor.vpos))
21122 last_text_row = it.glyph_row - 1;
21123
21124
21125
21126 if (pt_row)
21127 {
21128 w->cursor.vpos -= nrows_scrolled;
21129 w->cursor.y -= first_reusable_row->y - start_row->y;
21130 }
21131
21132
21133
21134
21135
21136 if (w->cursor.vpos < 0)
21137 {
21138 clear_glyph_matrix (w->desired_matrix);
21139 return false;
21140 }
21141
21142
21143 run.current_y = first_reusable_row->y;
21144 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21145 run.height = it.last_visible_y - run.current_y;
21146 dy = run.current_y - run.desired_y;
21147
21148 if (run.height)
21149 {
21150 #ifdef HAVE_WINDOW_SYSTEM
21151 update_begin (f);
21152 gui_update_window_begin (w);
21153 FRAME_RIF (f)->clear_window_mouse_face (w);
21154 FRAME_RIF (f)->scroll_run_hook (w, &run);
21155 gui_update_window_end (w, false, false);
21156 update_end (f);
21157 #endif
21158 }
21159
21160
21161 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21162 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21163 max_y = it.last_visible_y;
21164 for (row = first_reusable_row; row < first_row_to_display; ++row)
21165 {
21166 row->y -= dy;
21167 row->visible_height = row->height;
21168 if (row->y < min_y)
21169 row->visible_height -= min_y - row->y;
21170 if (row->y + row->height > max_y)
21171 row->visible_height -= row->y + row->height - max_y;
21172 if (row->fringe_bitmap_periodic_p)
21173 row->redraw_fringe_bitmaps_p = true;
21174 }
21175
21176
21177 eassert (nrows_scrolled > 0);
21178 rotate_matrix (w->current_matrix,
21179 start_vpos,
21180 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21181 -nrows_scrolled);
21182
21183
21184 for (row -= nrows_scrolled; row < bottom_row; ++row)
21185 row->enabled_p = false;
21186
21187
21188
21189 if (pt_row)
21190 {
21191 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21192 row < bottom_row
21193 && PT >= MATRIX_ROW_END_CHARPOS (row)
21194 && !row->ends_at_zv_p;
21195 row++)
21196 {
21197 w->cursor.vpos++;
21198 w->cursor.y = row->y;
21199 }
21200 if (row < bottom_row)
21201 {
21202
21203
21204
21205
21206 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21207 {
21208 if (!set_cursor_from_row (w, row, w->current_matrix,
21209 0, 0, 0, 0))
21210 {
21211 clear_glyph_matrix (w->desired_matrix);
21212 return false;
21213 }
21214 }
21215 else
21216 {
21217 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21218 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21219
21220 for (; glyph < end
21221 && (!BUFFERP (glyph->object)
21222 || glyph->charpos < PT);
21223 glyph++)
21224 {
21225 w->cursor.hpos++;
21226 w->cursor.x += glyph->pixel_width;
21227 }
21228 }
21229 }
21230 }
21231
21232
21233
21234
21235 if (last_text_row)
21236 adjust_window_ends (w, last_text_row, false);
21237 else
21238 w->window_end_vpos -= nrows_scrolled;
21239
21240 w->window_end_valid = false;
21241 w->desired_matrix->no_scrolling_p = true;
21242
21243 #ifdef GLYPH_DEBUG
21244 debug_method_add (w, "try_window_reusing_current_matrix 2");
21245 #endif
21246 return true;
21247 }
21248
21249 return false;
21250 }
21251
21252
21253
21254
21255
21256
21257
21258 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21259 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21260 ptrdiff_t *, ptrdiff_t *);
21261 static struct glyph_row *
21262 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21263 struct glyph_row *);
21264
21265
21266
21267
21268
21269
21270
21271 static struct glyph_row *
21272 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21273 struct glyph_row *start)
21274 {
21275 struct glyph_row *row, *row_found;
21276
21277
21278
21279
21280 row_found = NULL;
21281 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21282 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21283 {
21284 eassert (row->enabled_p);
21285 row_found = row;
21286 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21287 break;
21288 ++row;
21289 }
21290
21291 return row_found;
21292 }
21293
21294
21295
21296
21297
21298
21299
21300
21301
21302
21303
21304
21305 static struct glyph_row *
21306 find_last_unchanged_at_beg_row (struct window *w)
21307 {
21308 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21309 struct glyph_row *row;
21310 struct glyph_row *row_found = NULL;
21311 int yb = window_text_bottom_y (w);
21312
21313
21314 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21315 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21316 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21317 ++row)
21318 {
21319 if (
21320
21321 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21322
21323
21324 && !row->ends_at_zv_p
21325
21326
21327
21328 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21329 && (row->continued_p
21330 || row->exact_window_width_line_p))
21331
21332
21333
21334
21335
21336
21337
21338 && CHARPOS (row->end.pos) <= ZV)
21339 row_found = row;
21340
21341
21342 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21343 break;
21344 }
21345
21346 return row_found;
21347 }
21348
21349
21350
21351
21352
21353
21354
21355
21356
21357
21358
21359
21360
21361
21362 static struct glyph_row *
21363 find_first_unchanged_at_end_row (struct window *w,
21364 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21365 {
21366 struct glyph_row *row;
21367 struct glyph_row *row_found = NULL;
21368
21369 *delta = *delta_bytes = 0;
21370
21371
21372
21373 eassert (w->window_end_valid);
21374
21375
21376
21377
21378 if (w->window_end_pos >= END_UNCHANGED)
21379 return NULL;
21380
21381
21382 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21383
21384
21385 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21386 {
21387
21388
21389
21390
21391
21392 ptrdiff_t Z_old =
21393 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21394 ptrdiff_t Z_BYTE_old =
21395 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21396 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21397 struct glyph_row *first_text_row
21398 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21399
21400 *delta = Z - Z_old;
21401 *delta_bytes = Z_BYTE - Z_BYTE_old;
21402
21403
21404
21405
21406
21407
21408
21409 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21410 last_unchanged_pos_old = last_unchanged_pos - *delta;
21411
21412
21413
21414 for (; row > first_text_row; --row)
21415 {
21416
21417
21418 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21419 break;
21420
21421 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21422 row_found = row;
21423 }
21424 }
21425
21426 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21427
21428 return row_found;
21429 }
21430
21431
21432
21433
21434
21435
21436
21437
21438 static void
21439 sync_frame_with_window_matrix_rows (struct window *w)
21440 {
21441 struct frame *f = XFRAME (w->frame);
21442 struct glyph_row *window_row, *window_row_end, *frame_row;
21443
21444
21445
21446 eassert (BUFFERP (w->contents));
21447 eassert (WINDOW_FULL_WIDTH_P (w));
21448 eassert (!FRAME_WINDOW_P (f));
21449
21450
21451
21452
21453
21454 window_row = w->current_matrix->rows;
21455 window_row_end = window_row + w->current_matrix->nrows;
21456 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21457 while (window_row < window_row_end)
21458 {
21459 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21460 struct glyph *end = window_row->glyphs[LAST_AREA];
21461
21462 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21463 frame_row->glyphs[TEXT_AREA] = start;
21464 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21465 frame_row->glyphs[LAST_AREA] = end;
21466
21467
21468
21469 if (!window_row->enabled_p)
21470 frame_row->enabled_p = false;
21471
21472 ++window_row, ++frame_row;
21473 }
21474 }
21475
21476
21477
21478
21479
21480
21481
21482 struct glyph_row *
21483 row_containing_pos (struct window *w, ptrdiff_t charpos,
21484 struct glyph_row *start, struct glyph_row *end, int dy)
21485 {
21486 struct glyph_row *row = start;
21487 struct glyph_row *best_row = NULL;
21488 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21489 int last_y;
21490
21491
21492 if (row->tab_line_p)
21493 ++row;
21494 if (row->mode_line_p)
21495 ++row;
21496
21497 if ((end && row >= end) || !row->enabled_p)
21498 return NULL;
21499
21500 last_y = window_text_bottom_y (w) - dy;
21501
21502 while (true)
21503 {
21504
21505 if ((end && row >= end) || !row->enabled_p)
21506 return NULL;
21507
21508
21509
21510 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21511 return NULL;
21512
21513
21514 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21515 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21516
21517
21518
21519
21520 && !row_for_charpos_p (row, charpos)))
21521 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21522 {
21523 struct glyph *g;
21524
21525 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21526 || (!best_row && !row->continued_p))
21527 return row;
21528
21529
21530
21531
21532 for (g = row->glyphs[TEXT_AREA];
21533 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21534 g++)
21535 {
21536 if (!STRINGP (g->object))
21537 {
21538 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21539 {
21540 mindif = eabs (g->charpos - charpos);
21541 best_row = row;
21542
21543 if (mindif == 0)
21544 return best_row;
21545 }
21546 }
21547 }
21548 }
21549 else if (best_row && !row->continued_p)
21550 return best_row;
21551 ++row;
21552 }
21553 }
21554
21555
21556
21557
21558
21559
21560
21561
21562
21563
21564
21565
21566
21567
21568
21569
21570
21571
21572
21573
21574
21575
21576
21577
21578
21579
21580
21581
21582
21583
21584
21585
21586
21587
21588
21589
21590
21591
21592
21593
21594
21595
21596
21597
21598 static int
21599 try_window_id (struct window *w)
21600 {
21601 struct frame *f = XFRAME (w->frame);
21602 struct glyph_matrix *current_matrix = w->current_matrix;
21603 struct glyph_matrix *desired_matrix = w->desired_matrix;
21604 struct glyph_row *last_unchanged_at_beg_row;
21605 struct glyph_row *first_unchanged_at_end_row;
21606 struct glyph_row *row;
21607 struct glyph_row *bottom_row;
21608 int bottom_vpos;
21609 struct it it;
21610 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21611 int dvpos, dy;
21612 struct text_pos start_pos;
21613 struct run run;
21614 int first_unchanged_at_end_vpos = 0;
21615 struct glyph_row *last_text_row, *last_text_row_at_end;
21616 struct text_pos start;
21617 ptrdiff_t first_changed_charpos, last_changed_charpos;
21618
21619 #ifdef GLYPH_DEBUG
21620 if (inhibit_try_window_id)
21621 return 0;
21622 #endif
21623
21624
21625 #if false
21626 #define GIVE_UP(X) \
21627 do { \
21628 redisplay_trace ("try_window_id give up %d\n", X); \
21629 return 0; \
21630 } while (false)
21631 #else
21632 #define GIVE_UP(X) return 0
21633 #endif
21634
21635 SET_TEXT_POS_FROM_MARKER (start, w->start);
21636
21637
21638
21639 if (MINI_WINDOW_P (w))
21640 GIVE_UP (1);
21641
21642
21643 if (windows_or_buffers_changed || f->cursor_type_changed)
21644 GIVE_UP (2);
21645
21646
21647
21648
21649 if (w->last_overlay_modified != OVERLAY_MODIFF)
21650 GIVE_UP (200);
21651
21652
21653
21654
21655
21656 if (current_buffer->clip_changed
21657 || current_buffer->prevent_redisplay_optimizations_p)
21658 GIVE_UP (3);
21659
21660
21661 if (!FRAME_WINDOW_P (f)
21662 && (!FRAME_LINE_INS_DEL_OK (f)
21663 || !WINDOW_FULL_WIDTH_P (w)))
21664 GIVE_UP (4);
21665
21666
21667 if (PT < CHARPOS (start))
21668 GIVE_UP (5);
21669
21670
21671 if (w->last_modified == 0)
21672 GIVE_UP (6);
21673
21674
21675 if (w->hscroll != 0)
21676 GIVE_UP (7);
21677
21678
21679 if (!w->window_end_valid)
21680 GIVE_UP (8);
21681
21682
21683 if (!NILP (Vshow_trailing_whitespace))
21684 GIVE_UP (11);
21685
21686
21687
21688 if (overlay_arrows_changed_p (false))
21689 GIVE_UP (12);
21690
21691
21692
21693
21694
21695 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21696 GIVE_UP (21);
21697
21698
21699
21700
21701
21702
21703
21704
21705
21706 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21707 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21708 GIVE_UP (22);
21709
21710
21711
21712 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21713 GIVE_UP (23);
21714
21715
21716
21717 if (EQ (Vdisplay_line_numbers, Qrelative)
21718 || EQ (Vdisplay_line_numbers, Qvisual)
21719 || (!NILP (Vdisplay_line_numbers)
21720 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21721 Qline_number_current_line,
21722 w->frame))))
21723 GIVE_UP (24);
21724
21725
21726
21727
21728 if (composition_break_at_point)
21729 GIVE_UP (27);
21730
21731
21732
21733
21734
21735 if (MODIFF > SAVE_MODIFF
21736
21737 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21738 {
21739 if (GPT - BEG < BEG_UNCHANGED)
21740 BEG_UNCHANGED = GPT - BEG;
21741 if (Z - GPT < END_UNCHANGED)
21742 END_UNCHANGED = Z - GPT;
21743 }
21744
21745
21746 first_changed_charpos = BEG + BEG_UNCHANGED;
21747 last_changed_charpos = Z - END_UNCHANGED;
21748
21749
21750
21751
21752
21753
21754 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21755 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21756 && ((last_changed_charpos < CHARPOS (start)
21757 && CHARPOS (start) == BEGV)
21758 || (last_changed_charpos < CHARPOS (start) - 1
21759 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21760 {
21761 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21762 struct glyph_row *r0;
21763
21764
21765
21766 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21767 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21768 Z_delta = Z - Z_old;
21769 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
21770
21771
21772
21773
21774 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
21775 GIVE_UP (13);
21776
21777
21778
21779
21780 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21781 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
21782 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
21783
21784 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
21785 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21786 {
21787
21788 if (Z_delta || Z_delta_bytes)
21789 {
21790 struct glyph_row *r1
21791 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
21792 increment_matrix_positions (w->current_matrix,
21793 MATRIX_ROW_VPOS (r0, current_matrix),
21794 MATRIX_ROW_VPOS (r1, current_matrix),
21795 Z_delta, Z_delta_bytes);
21796 }
21797
21798
21799 row = row_containing_pos (w, PT, r0, NULL, 0);
21800 if (row)
21801 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21802 return 1;
21803 }
21804 }
21805
21806
21807
21808
21809
21810 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
21811
21812
21813 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
21814 || first_changed_charpos == last_changed_charpos))
21815 {
21816 struct glyph_row *r0;
21817
21818
21819
21820
21821 if (PT >= MATRIX_ROW_END_CHARPOS (row))
21822 GIVE_UP (14);
21823
21824
21825
21826
21827 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21828 if (TEXT_POS_EQUAL_P (start, r0->minpos)
21829
21830 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
21831 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21832 {
21833
21834
21835 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
21836 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
21837
21838
21839 row = row_containing_pos (w, PT, r0, NULL, 0);
21840 if (row)
21841 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21842 return 2;
21843 }
21844 }
21845
21846
21847
21848
21849
21850
21851
21852
21853 if (CHARPOS (start) >= first_changed_charpos
21854 && CHARPOS (start) <= last_changed_charpos)
21855 GIVE_UP (15);
21856
21857
21858
21859
21860
21861 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
21862 if (!TEXT_POS_EQUAL_P (start, row->minpos))
21863 GIVE_UP (16);
21864
21865
21866
21867 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
21868 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
21869 GIVE_UP (20);
21870
21871
21872
21873
21874
21875 #ifdef HAVE_NTGUI
21876 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
21877 GIVE_UP (25);
21878 #endif
21879
21880
21881
21882
21883
21884
21885
21886 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
21887 if (last_unchanged_at_beg_row)
21888 {
21889
21890
21891
21892
21893 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
21894 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
21895 && last_unchanged_at_beg_row > w->current_matrix->rows)
21896 --last_unchanged_at_beg_row;
21897
21898 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
21899 GIVE_UP (17);
21900
21901 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
21902 GIVE_UP (18);
21903
21904
21905
21906 if (it.sp > 1
21907 && it.method == GET_FROM_IMAGE && it.image_id == -1)
21908 GIVE_UP (26);
21909 start_pos = it.current.pos;
21910
21911
21912
21913
21914 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
21915 current_matrix);
21916 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
21917 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
21918
21919 eassert (it.hpos == 0 && it.current_x == 0);
21920 }
21921 else
21922 {
21923
21924
21925 start_display (&it, w, start);
21926 it.vpos = it.first_vpos;
21927 start_pos = it.current.pos;
21928 }
21929
21930
21931
21932
21933
21934
21935
21936 first_unchanged_at_end_row
21937 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
21938 IF_DEBUG (debug_delta = delta);
21939 IF_DEBUG (debug_delta_bytes = delta_bytes);
21940
21941
21942
21943
21944
21945
21946 stop_pos = 0;
21947 if (first_unchanged_at_end_row)
21948 {
21949 eassert (last_unchanged_at_beg_row == NULL
21950 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
21951
21952
21953
21954
21955
21956 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
21957 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
21958 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
21959 < it.last_visible_y))
21960 ++first_unchanged_at_end_row;
21961
21962 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
21963 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
21964 >= it.last_visible_y))
21965 first_unchanged_at_end_row = NULL;
21966 else
21967 {
21968 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
21969 + delta);
21970 first_unchanged_at_end_vpos
21971 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
21972 eassert (stop_pos >= Z - END_UNCHANGED);
21973 }
21974 }
21975 else if (last_unchanged_at_beg_row == NULL)
21976 GIVE_UP (19);
21977
21978
21979 #ifdef GLYPH_DEBUG
21980
21981
21982
21983
21984 eassert (first_unchanged_at_end_row == NULL
21985 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
21986
21987 debug_last_unchanged_at_beg_vpos
21988 = (last_unchanged_at_beg_row
21989 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
21990 : -1);
21991 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
21992
21993 #endif
21994
21995
21996
21997
21998
21999 w->cursor.vpos = -1;
22000 last_text_row = NULL;
22001 overlay_arrow_seen = false;
22002 if (it.current_y < it.last_visible_y
22003 && !f->fonts_changed
22004 && (first_unchanged_at_end_row == NULL
22005 || IT_CHARPOS (it) < stop_pos))
22006 it.glyph_row->reversed_p = false;
22007 while (it.current_y < it.last_visible_y
22008 && !f->fonts_changed
22009 && (first_unchanged_at_end_row == NULL
22010 || IT_CHARPOS (it) < stop_pos))
22011 {
22012 if (display_line (&it, -1))
22013 last_text_row = it.glyph_row - 1;
22014 }
22015
22016 if (f->fonts_changed)
22017 return -1;
22018
22019
22020
22021
22022
22023
22024
22025
22026
22027
22028
22029 if (!w->window_end_valid)
22030 {
22031 clear_glyph_matrix (w->desired_matrix);
22032 return -1;
22033 }
22034
22035
22036
22037
22038 if (first_unchanged_at_end_row
22039
22040
22041 && it.current_y < it.last_visible_y)
22042 {
22043 dvpos = (it.vpos
22044 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22045 current_matrix));
22046 dy = it.current_y - first_unchanged_at_end_row->y;
22047 run.current_y = first_unchanged_at_end_row->y;
22048 run.desired_y = run.current_y + dy;
22049 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22050 }
22051 else
22052 {
22053 delta = delta_bytes = dvpos = dy
22054 = run.current_y = run.desired_y = run.height = 0;
22055 first_unchanged_at_end_row = NULL;
22056 }
22057 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22058
22059
22060
22061
22062
22063
22064
22065
22066
22067
22068 if (w->cursor.vpos < 0)
22069 {
22070
22071 if (PT < CHARPOS (start_pos)
22072 && last_unchanged_at_beg_row)
22073 {
22074 row = row_containing_pos (w, PT,
22075 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22076 last_unchanged_at_beg_row + 1, 0);
22077 if (row)
22078 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22079 }
22080
22081
22082 else if (first_unchanged_at_end_row)
22083 {
22084 row = row_containing_pos (w, PT - delta,
22085 first_unchanged_at_end_row, NULL, 0);
22086 if (row)
22087 set_cursor_from_row (w, row, w->current_matrix, delta,
22088 delta_bytes, dy, dvpos);
22089 }
22090
22091
22092 if (w->cursor.vpos < 0)
22093 {
22094 clear_glyph_matrix (w->desired_matrix);
22095 return -1;
22096 }
22097 }
22098
22099
22100 {
22101 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22102 int bot_scroll_margin = top_scroll_margin;
22103 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22104
22105 if (window_wants_header_line (w))
22106 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22107 if (window_wants_tab_line (w))
22108 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22109
22110 if ((w->cursor.y < top_scroll_margin
22111 && CHARPOS (start) > BEGV)
22112
22113
22114 || (w->cursor.y
22115 + (cursor_row_fully_visible_p (w, false, true, true)
22116 ? 1
22117 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22118 {
22119 w->cursor.vpos = -1;
22120 clear_glyph_matrix (w->desired_matrix);
22121 return -1;
22122 }
22123 }
22124
22125
22126
22127
22128 if (dy && run.height)
22129 {
22130 update_begin (f);
22131
22132 if (FRAME_WINDOW_P (f))
22133 {
22134 #ifdef HAVE_WINDOW_SYSTEM
22135 gui_update_window_begin (w);
22136 FRAME_RIF (f)->clear_window_mouse_face (w);
22137 FRAME_RIF (f)->scroll_run_hook (w, &run);
22138 gui_update_window_end (w, false, false);
22139 #endif
22140 }
22141 else
22142 {
22143
22144
22145 int from_vpos
22146 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22147 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22148 int end = (WINDOW_TOP_EDGE_LINE (w)
22149 + window_wants_tab_line (w)
22150 + window_wants_header_line (w)
22151 + window_internal_height (w));
22152
22153 gui_clear_window_mouse_face (w);
22154
22155
22156 if (dvpos > 0)
22157 {
22158
22159
22160 set_terminal_window (f, end);
22161
22162
22163
22164 if (!FRAME_SCROLL_REGION_OK (f))
22165 ins_del_lines (f, end - dvpos, -dvpos);
22166
22167
22168
22169 ins_del_lines (f, from, dvpos);
22170 }
22171 else if (dvpos < 0)
22172 {
22173
22174
22175 set_terminal_window (f, end);
22176
22177
22178
22179
22180
22181 ins_del_lines (f, from + dvpos, dvpos);
22182
22183
22184
22185 if (!FRAME_SCROLL_REGION_OK (f))
22186 ins_del_lines (f, end + dvpos, -dvpos);
22187 }
22188
22189 set_terminal_window (f, 0);
22190 }
22191
22192 update_end (f);
22193 }
22194
22195
22196
22197
22198 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22199 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22200 if (dvpos < 0)
22201 {
22202 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22203 bottom_vpos, dvpos);
22204 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22205 bottom_vpos);
22206 }
22207 else if (dvpos > 0)
22208 {
22209 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22210 bottom_vpos, dvpos);
22211 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22212 first_unchanged_at_end_vpos + dvpos);
22213 }
22214
22215
22216
22217 if (!FRAME_WINDOW_P (f))
22218 sync_frame_with_window_matrix_rows (w);
22219
22220
22221 if (delta || delta_bytes)
22222 increment_matrix_positions (current_matrix,
22223 first_unchanged_at_end_vpos + dvpos,
22224 bottom_vpos, delta, delta_bytes);
22225
22226
22227 if (dy)
22228 shift_glyph_matrix (w, current_matrix,
22229 first_unchanged_at_end_vpos + dvpos,
22230 bottom_vpos, dy);
22231
22232 if (first_unchanged_at_end_row)
22233 {
22234 first_unchanged_at_end_row += dvpos;
22235 if (first_unchanged_at_end_row->y >= it.last_visible_y
22236 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22237 first_unchanged_at_end_row = NULL;
22238 }
22239
22240
22241
22242 last_text_row_at_end = NULL;
22243 if (dy < 0)
22244 {
22245
22246
22247
22248
22249
22250 int last_vpos = w->window_end_vpos + dvpos;
22251 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22252
22253
22254 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22255
22256
22257
22258
22259 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22260 {
22261 init_to_row_start (&it, w, last_row);
22262 it.vpos = last_vpos;
22263 it.current_y = last_row->y;
22264 }
22265 else
22266 {
22267 init_to_row_end (&it, w, last_row);
22268 it.vpos = 1 + last_vpos;
22269 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22270 ++last_row;
22271 }
22272
22273
22274
22275 it.continuation_lines_width = last_row->continuation_lines_width;
22276 it.hpos = it.current_x = 0;
22277
22278
22279 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22280 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22281 {
22282
22283
22284
22285
22286 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22287 if (display_line (&it, w->cursor.vpos))
22288 last_text_row_at_end = it.glyph_row - 1;
22289 }
22290 }
22291
22292
22293 if (first_unchanged_at_end_row && !last_text_row_at_end)
22294 {
22295
22296
22297
22298
22299 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22300 row = find_last_row_displaying_text (w->current_matrix, &it,
22301 first_unchanged_at_end_row);
22302 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22303 adjust_window_ends (w, row, true);
22304 eassert (w->window_end_bytepos >= 0);
22305 IF_DEBUG (debug_method_add (w, "A"));
22306 }
22307 else if (last_text_row_at_end)
22308 {
22309 adjust_window_ends (w, last_text_row_at_end, false);
22310 eassert (w->window_end_bytepos >= 0);
22311 IF_DEBUG (debug_method_add (w, "B"));
22312 }
22313 else if (last_text_row)
22314 {
22315
22316
22317
22318 adjust_window_ends (w, last_text_row, false);
22319 eassert (w->window_end_bytepos >= 0);
22320 }
22321 else if (first_unchanged_at_end_row == NULL
22322 && last_text_row == NULL
22323 && last_text_row_at_end == NULL)
22324 {
22325
22326
22327 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22328 int vpos = w->window_end_vpos;
22329 struct glyph_row *current_row = current_matrix->rows + vpos;
22330 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22331
22332 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22333 {
22334 eassert (first_vpos <= vpos);
22335 if (desired_row->enabled_p)
22336 {
22337 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22338 row = desired_row;
22339 }
22340 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22341 row = current_row;
22342 }
22343
22344 w->window_end_vpos = vpos + 1;
22345 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22346 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22347 eassert (w->window_end_bytepos >= 0);
22348 IF_DEBUG (debug_method_add (w, "C"));
22349 }
22350 else
22351 emacs_abort ();
22352
22353 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22354 debug_end_vpos = w->window_end_vpos));
22355
22356
22357 w->window_end_valid = false;
22358 w->desired_matrix->no_scrolling_p = true;
22359 return 3;
22360
22361 #undef GIVE_UP
22362 }
22363
22364
22365
22366
22367
22368
22369
22370 #ifdef GLYPH_DEBUG
22371
22372 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22373 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22374 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22375
22376
22377
22378
22379
22380
22381
22382
22383 void
22384 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22385 {
22386 int i;
22387 for (i = 0; i < matrix->nrows; ++i)
22388 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22389 }
22390
22391
22392
22393
22394
22395 void
22396 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22397 {
22398 if (glyph->type == CHAR_GLYPH
22399 || glyph->type == GLYPHLESS_GLYPH)
22400 {
22401 fprintf (stderr,
22402 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22403 glyph - row->glyphs[TEXT_AREA],
22404 (glyph->type == CHAR_GLYPH
22405 ? 'C'
22406 : 'G'),
22407 glyph->charpos,
22408 (BUFFERP (glyph->object)
22409 ? 'B'
22410 : (STRINGP (glyph->object)
22411 ? 'S'
22412 : (NILP (glyph->object)
22413 ? '0'
22414 : '-'))),
22415 glyph->pixel_width,
22416 glyph->u.ch,
22417 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22418 ? (int) glyph->u.ch
22419 : '.'),
22420 glyph->face_id,
22421 glyph->left_box_line_p,
22422 glyph->right_box_line_p);
22423 }
22424 else if (glyph->type == STRETCH_GLYPH)
22425 {
22426 fprintf (stderr,
22427 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22428 glyph - row->glyphs[TEXT_AREA],
22429 'S',
22430 glyph->charpos,
22431 (BUFFERP (glyph->object)
22432 ? 'B'
22433 : (STRINGP (glyph->object)
22434 ? 'S'
22435 : (NILP (glyph->object)
22436 ? '0'
22437 : '-'))),
22438 glyph->pixel_width,
22439 0u,
22440 ' ',
22441 glyph->face_id,
22442 glyph->left_box_line_p,
22443 glyph->right_box_line_p);
22444 }
22445 else if (glyph->type == IMAGE_GLYPH)
22446 {
22447 fprintf (stderr,
22448 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22449 glyph - row->glyphs[TEXT_AREA],
22450 'I',
22451 glyph->charpos,
22452 (BUFFERP (glyph->object)
22453 ? 'B'
22454 : (STRINGP (glyph->object)
22455 ? 'S'
22456 : (NILP (glyph->object)
22457 ? '0'
22458 : '-'))),
22459 glyph->pixel_width,
22460 (unsigned int) glyph->u.img_id,
22461 '.',
22462 glyph->face_id,
22463 glyph->left_box_line_p,
22464 glyph->right_box_line_p);
22465 }
22466 else if (glyph->type == COMPOSITE_GLYPH)
22467 {
22468 fprintf (stderr,
22469 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22470 glyph - row->glyphs[TEXT_AREA],
22471 '+',
22472 glyph->charpos,
22473 (BUFFERP (glyph->object)
22474 ? 'B'
22475 : (STRINGP (glyph->object)
22476 ? 'S'
22477 : (NILP (glyph->object)
22478 ? '0'
22479 : '-'))),
22480 glyph->pixel_width,
22481 (unsigned int) glyph->u.cmp.id);
22482 if (glyph->u.cmp.automatic)
22483 fprintf (stderr,
22484 "[%d-%d]",
22485 glyph->slice.cmp.from, glyph->slice.cmp.to);
22486 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22487 glyph->face_id,
22488 glyph->left_box_line_p,
22489 glyph->right_box_line_p);
22490 }
22491 else if (glyph->type == XWIDGET_GLYPH)
22492 {
22493 #ifndef HAVE_XWIDGETS
22494 eassume (false);
22495 #else
22496 fprintf (stderr,
22497 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22498 glyph - row->glyphs[TEXT_AREA],
22499 'X',
22500 glyph->charpos,
22501 (BUFFERP (glyph->object)
22502 ? 'B'
22503 : (STRINGP (glyph->object)
22504 ? 'S'
22505 : '-')),
22506 glyph->pixel_width,
22507 glyph->u.xwidget,
22508 '.',
22509 glyph->face_id,
22510 glyph->left_box_line_p,
22511 glyph->right_box_line_p);
22512 #endif
22513 }
22514 }
22515
22516
22517
22518
22519
22520
22521
22522 void
22523 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22524 {
22525 if (glyphs != 1)
22526 {
22527 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22528 "==============================================================================\n"),
22529 stderr);
22530 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22531 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22532 vpos,
22533 MATRIX_ROW_START_CHARPOS (row),
22534 MATRIX_ROW_END_CHARPOS (row),
22535 row->used[TEXT_AREA],
22536 row->contains_overlapping_glyphs_p,
22537 row->enabled_p,
22538 row->truncated_on_left_p,
22539 row->truncated_on_right_p,
22540 row->continued_p,
22541 MATRIX_ROW_CONTINUATION_LINE_P (row),
22542 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22543 row->ends_at_zv_p,
22544 row->fill_line_p,
22545 row->ends_in_middle_of_char_p,
22546 row->starts_in_middle_of_char_p,
22547 row->mouse_face_p,
22548 row->x,
22549 row->y,
22550 row->pixel_width,
22551 row->height,
22552 row->visible_height,
22553 row->ascent,
22554 row->phys_ascent);
22555
22556 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22557 row->end.overlay_string_index,
22558 row->continuation_lines_width);
22559 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22560 CHARPOS (row->start.string_pos),
22561 CHARPOS (row->end.string_pos));
22562 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22563 row->end.dpvec_index);
22564 }
22565
22566 if (glyphs > 1)
22567 {
22568 int area;
22569
22570 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22571 {
22572 struct glyph *glyph = row->glyphs[area];
22573 struct glyph *glyph_end = glyph + row->used[area];
22574
22575
22576 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22577 ++glyph_end;
22578
22579 if (glyph < glyph_end)
22580 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22581 stderr);
22582
22583 for (; glyph < glyph_end; ++glyph)
22584 dump_glyph (row, glyph, area);
22585 }
22586 }
22587 else if (glyphs == 1)
22588 {
22589 int area;
22590 char s[SHRT_MAX + 4];
22591
22592 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22593 {
22594 int i;
22595
22596 for (i = 0; i < row->used[area]; ++i)
22597 {
22598 struct glyph *glyph = row->glyphs[area] + i;
22599 if (i == row->used[area] - 1
22600 && area == TEXT_AREA
22601 && NILP (glyph->object)
22602 && glyph->type == CHAR_GLYPH
22603 && glyph->u.ch == ' ')
22604 {
22605 strcpy (&s[i], "[\\n]");
22606 i += 4;
22607 }
22608 else if (glyph->type == CHAR_GLYPH
22609 && glyph->u.ch < 0x80
22610 && glyph->u.ch >= ' ')
22611 s[i] = glyph->u.ch;
22612 else
22613 s[i] = '.';
22614 }
22615
22616 s[i] = '\0';
22617 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22618 }
22619 }
22620 }
22621
22622
22623 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22624 Sdump_glyph_matrix, 0, 1, "p",
22625 doc:
22626
22627
22628
22629
22630
22631 )
22632 (Lisp_Object glyphs)
22633 {
22634 struct window *w = XWINDOW (selected_window);
22635 struct buffer *buffer = XBUFFER (w->contents);
22636
22637 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22638 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22639 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22640 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22641 fputs ("=============================================\n", stderr);
22642 dump_glyph_matrix (w->current_matrix,
22643 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22644 return Qnil;
22645 }
22646
22647
22648 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22649 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22650 )
22651 (void)
22652 {
22653 struct frame *f = XFRAME (selected_frame);
22654
22655 if (f->current_matrix)
22656 dump_glyph_matrix (f->current_matrix, 1);
22657 else
22658 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22659 return Qnil;
22660 }
22661
22662
22663 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22664 doc:
22665
22666
22667
22668
22669 )
22670 (Lisp_Object row, Lisp_Object glyphs)
22671 {
22672 struct glyph_matrix *matrix;
22673 EMACS_INT vpos;
22674
22675 if (NILP (row))
22676 {
22677 int d1, d2, d3, d4, d5, ypos;
22678 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22679 &d1, &d2, &d3, &d4, &d5, &ypos);
22680 if (visible_p)
22681 vpos = ypos;
22682 else
22683 vpos = 0;
22684 }
22685 else
22686 {
22687 CHECK_FIXNUM (row);
22688 vpos = XFIXNUM (row);
22689 }
22690 matrix = XWINDOW (selected_window)->current_matrix;
22691 if (vpos >= 0 && vpos < matrix->nrows)
22692 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22693 vpos,
22694 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22695 return Qnil;
22696 }
22697
22698
22699 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22700 doc:
22701
22702
22703
22704
22705
22706
22707 )
22708 (Lisp_Object row, Lisp_Object glyphs)
22709 {
22710 #if defined (HAVE_WINDOW_SYSTEM)
22711 struct frame *sf = SELECTED_FRAME ();
22712 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22713 ? XWINDOW (sf->tab_bar_window)->current_matrix
22714 : sf->current_matrix;
22715 EMACS_INT vpos;
22716
22717 if (NILP (row))
22718 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22719 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22720 else
22721 {
22722 CHECK_FIXNUM (row);
22723 vpos = XFIXNUM (row);
22724 }
22725 if (vpos >= 0 && vpos < m->nrows)
22726 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22727 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22728 #endif
22729 return Qnil;
22730 }
22731
22732 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22733 doc:
22734
22735
22736
22737
22738
22739
22740 )
22741 (Lisp_Object row, Lisp_Object glyphs)
22742 {
22743 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22744 struct frame *sf = SELECTED_FRAME ();
22745 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22746 EMACS_INT vpos;
22747
22748 if (NILP (row))
22749 vpos = 0;
22750 else
22751 {
22752 CHECK_FIXNUM (row);
22753 vpos = XFIXNUM (row);
22754 }
22755 if (vpos >= 0 && vpos < m->nrows)
22756 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22757 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22758 #endif
22759 return Qnil;
22760 }
22761
22762
22763 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22764 doc:
22765 )
22766 (Lisp_Object arg)
22767 {
22768 if (NILP (arg))
22769 trace_redisplay_p = !trace_redisplay_p;
22770 else
22771 {
22772 arg = Fprefix_numeric_value (arg);
22773 trace_redisplay_p = XFIXNUM (arg) > 0;
22774 }
22775
22776 return Qnil;
22777 }
22778
22779
22780 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
22781 doc:
22782 )
22783 (ptrdiff_t nargs, Lisp_Object *args)
22784 {
22785 Lisp_Object s = Fformat (nargs, args);
22786 fwrite (SDATA (s), 1, SBYTES (s), stderr);
22787 return Qnil;
22788 }
22789
22790 #endif
22791
22792
22793
22794
22795
22796
22797
22798
22799
22800
22801
22802 static struct glyph_row *
22803 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
22804 {
22805 struct frame *f = XFRAME (WINDOW_FRAME (w));
22806 struct buffer *buffer = XBUFFER (w->contents);
22807 struct buffer *old = current_buffer;
22808 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
22809 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
22810 const unsigned char *arrow_end = arrow_string + arrow_len;
22811 const unsigned char *p;
22812 struct it it;
22813 bool multibyte_p;
22814 int n_glyphs_before;
22815
22816 set_buffer_temp (buffer);
22817 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
22818 scratch_glyph_row.reversed_p = false;
22819 it.glyph_row->used[TEXT_AREA] = 0;
22820 SET_TEXT_POS (it.position, 0, 0);
22821
22822 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
22823 p = arrow_string;
22824 while (p < arrow_end)
22825 {
22826 Lisp_Object face, ilisp;
22827
22828
22829 if (multibyte_p)
22830 it.c = it.char_to_display = check_char_and_length (p, &it.len);
22831 else
22832 {
22833 it.c = it.char_to_display = *p, it.len = 1;
22834 if (! ASCII_CHAR_P (it.c))
22835 it.char_to_display = BYTE8_TO_CHAR (it.c);
22836 }
22837 p += it.len;
22838
22839
22840 ilisp = make_fixnum (char_num++);
22841 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
22842 it.face_id = compute_char_face (f, it.char_to_display, face);
22843
22844
22845 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
22846 SET_TEXT_POS (it.position, -1, -1);
22847 PRODUCE_GLYPHS (&it);
22848
22849
22850
22851 if (it.current_x > it.last_visible_x)
22852 {
22853 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
22854 break;
22855 }
22856 }
22857
22858 set_buffer_temp (old);
22859 return it.glyph_row;
22860 }
22861
22862
22863
22864
22865
22866 static void
22867 insert_left_trunc_glyphs (struct it *it)
22868 {
22869 struct it truncate_it;
22870 struct glyph *from, *end, *to, *toend;
22871
22872 eassert (!FRAME_WINDOW_P (it->f)
22873 || (!it->glyph_row->reversed_p
22874 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
22875 || (it->glyph_row->reversed_p
22876 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
22877
22878
22879 truncate_it = *it;
22880 truncate_it.current_x = 0;
22881 truncate_it.face_id = DEFAULT_FACE_ID;
22882 truncate_it.glyph_row = &scratch_glyph_row;
22883 truncate_it.area = TEXT_AREA;
22884 truncate_it.glyph_row->used[TEXT_AREA] = 0;
22885 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
22886 truncate_it.object = Qnil;
22887 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
22888
22889
22890 if (!it->glyph_row->reversed_p)
22891 {
22892 short tused = truncate_it.glyph_row->used[TEXT_AREA];
22893
22894 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
22895 end = from + tused;
22896 to = it->glyph_row->glyphs[TEXT_AREA];
22897 toend = to + it->glyph_row->used[TEXT_AREA];
22898 if (FRAME_WINDOW_P (it->f))
22899 {
22900
22901
22902
22903
22904
22905
22906
22907 int w = 0;
22908 struct glyph *g = to;
22909 short used;
22910
22911
22912
22913
22914
22915
22916 it->glyph_row->x = 0;
22917 while (g < toend && w < it->truncation_pixel_width)
22918 {
22919 w += g->pixel_width;
22920 ++g;
22921 }
22922 if (g - to - tused > 0)
22923 {
22924 memmove (to + tused, g, (toend - g) * sizeof(*g));
22925 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
22926 }
22927 used = it->glyph_row->used[TEXT_AREA];
22928 if (it->glyph_row->truncated_on_right_p
22929 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
22930 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
22931 == STRETCH_GLYPH)
22932 {
22933 int extra = w - it->truncation_pixel_width;
22934
22935 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
22936 }
22937 }
22938
22939 while (from < end)
22940 *to++ = *from++;
22941
22942
22943 if (!FRAME_WINDOW_P (it->f))
22944 {
22945 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
22946 {
22947 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
22948 while (from < end)
22949 *to++ = *from++;
22950 }
22951 }
22952
22953 if (to > toend)
22954 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
22955 }
22956 else
22957 {
22958 short tused = truncate_it.glyph_row->used[TEXT_AREA];
22959
22960
22961
22962 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
22963 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
22964 toend = it->glyph_row->glyphs[TEXT_AREA];
22965 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
22966 if (FRAME_WINDOW_P (it->f))
22967 {
22968 int w = 0;
22969 struct glyph *g = to;
22970
22971 while (g >= toend && w < it->truncation_pixel_width)
22972 {
22973 w += g->pixel_width;
22974 --g;
22975 }
22976 if (to - g - tused > 0)
22977 to = g + tused;
22978 if (it->glyph_row->truncated_on_right_p
22979 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
22980 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
22981 {
22982 int extra = w - it->truncation_pixel_width;
22983
22984 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
22985 }
22986 }
22987
22988 while (from >= end && to >= toend)
22989 *to-- = *from--;
22990 if (!FRAME_WINDOW_P (it->f))
22991 {
22992 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
22993 {
22994 from =
22995 truncate_it.glyph_row->glyphs[TEXT_AREA]
22996 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
22997 while (from >= end && to >= toend)
22998 *to-- = *from--;
22999 }
23000 }
23001 if (from >= end)
23002 {
23003
23004
23005 int move_by = from - end + 1;
23006 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
23007 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
23008
23009 for ( ; g >= g0; g--)
23010 g[move_by] = *g;
23011 while (from >= end)
23012 *to-- = *from--;
23013 it->glyph_row->used[TEXT_AREA] += move_by;
23014 }
23015 }
23016 }
23017
23018
23019 unsigned
23020 row_hash (struct glyph_row *row)
23021 {
23022 int area, k;
23023 unsigned hashval = 0;
23024
23025 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23026 for (k = 0; k < row->used[area]; ++k)
23027 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23028 + row->glyphs[area][k].u.val
23029 + row->glyphs[area][k].face_id
23030 + row->glyphs[area][k].padding_p
23031 + (row->glyphs[area][k].type << 2));
23032
23033 return hashval;
23034 }
23035
23036
23037
23038
23039
23040
23041
23042
23043
23044
23045
23046
23047
23048
23049
23050
23051
23052
23053 static void
23054 compute_line_metrics (struct it *it)
23055 {
23056 struct glyph_row *row = it->glyph_row;
23057
23058 if (FRAME_WINDOW_P (it->f))
23059 {
23060 int i, min_y, max_y;
23061
23062
23063
23064
23065 if (row->height == 0)
23066 {
23067 if (it->max_ascent + it->max_descent == 0)
23068 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23069 row->ascent = it->max_ascent;
23070 row->height = it->max_ascent + it->max_descent;
23071 row->phys_ascent = it->max_phys_ascent;
23072 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23073 row->extra_line_spacing = it->max_extra_line_spacing;
23074 }
23075
23076
23077 row->pixel_width = row->x;
23078 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23079 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23080
23081 eassert (row->pixel_width >= 0);
23082 eassert (row->ascent >= 0 && row->height > 0);
23083
23084 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23085 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23086
23087
23088
23089
23090 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23091 && row->phys_ascent > row->ascent)
23092 {
23093 row->height += row->phys_ascent - row->ascent;
23094 row->ascent = row->phys_ascent;
23095 }
23096
23097
23098 row->visible_height = row->height;
23099
23100 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23101 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23102
23103 if (row->y < min_y)
23104 row->visible_height -= min_y - row->y;
23105 if (row->y + row->height > max_y)
23106 row->visible_height -= row->y + row->height - max_y;
23107 }
23108 else
23109 {
23110 row->pixel_width = row->used[TEXT_AREA];
23111 if (row->continued_p)
23112 row->pixel_width -= it->continuation_pixel_width;
23113 else if (row->truncated_on_right_p)
23114 row->pixel_width -= it->truncation_pixel_width;
23115 row->ascent = row->phys_ascent = 0;
23116 row->height = row->phys_height = row->visible_height = 1;
23117 row->extra_line_spacing = 0;
23118 }
23119
23120
23121 row->hash = row_hash (row);
23122
23123 it->max_ascent = it->max_descent = 0;
23124 it->max_phys_ascent = it->max_phys_descent = 0;
23125 }
23126
23127
23128 static void
23129 clear_position (struct it *it)
23130 {
23131 it->position.charpos = 0;
23132 it->position.bytepos = 0;
23133 }
23134
23135
23136
23137
23138
23139
23140
23141
23142
23143
23144
23145
23146
23147 static bool
23148 append_space_for_newline (struct it *it, bool default_face_p)
23149 {
23150 int n = it->glyph_row->used[TEXT_AREA];
23151
23152 if (it->glyph_row->glyphs[TEXT_AREA] + n
23153 < it->glyph_row->glyphs[1 + TEXT_AREA])
23154 {
23155
23156
23157
23158
23159 enum display_element_type saved_what = it->what;
23160 int saved_c = it->c, saved_len = it->len;
23161 int saved_char_to_display = it->char_to_display;
23162 int saved_x = it->current_x;
23163 const int saved_face_id = it->face_id;
23164 bool saved_box_end = it->end_of_box_run_p;
23165 struct text_pos saved_pos = it->position;
23166 Lisp_Object saved_object = it->object;
23167 struct face *face;
23168
23169 it->what = IT_CHARACTER;
23170 clear_position (it);
23171 it->object = Qnil;
23172 it->len = 1;
23173
23174 int char_width = 1;
23175
23176 if (default_face_p
23177 #ifdef HAVE_WINDOW_SYSTEM
23178 || FRAME_WINDOW_P (it->f)
23179 #endif
23180 )
23181 {
23182 const int local_default_face_id =
23183 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23184
23185 #ifdef HAVE_WINDOW_SYSTEM
23186 if (FRAME_WINDOW_P (it->f))
23187 {
23188 struct face *default_face
23189 = FACE_FROM_ID (it->f, local_default_face_id);
23190 struct font *font = (default_face->font
23191 ? default_face->font
23192 : FRAME_FONT (it->f));
23193 char_width = (font->average_width
23194 ? font->average_width
23195 : font->space_width);
23196 }
23197 #endif
23198 if (default_face_p)
23199 it->face_id = local_default_face_id;
23200 }
23201
23202
23203
23204
23205 const int indicator_column =
23206 fill_column_indicator_column (it, char_width);
23207 int saved_end_of_box_run = it->end_of_box_run_p;
23208 bool should_keep_end_of_box_run = false;
23209
23210 if (it->current_x == indicator_column)
23211 {
23212 it->c = it->char_to_display
23213 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23214 it->face_id
23215 = merge_faces (it->w, Qfill_column_indicator,
23216 0, saved_face_id);
23217 face = FACE_FROM_ID (it->f, it->face_id);
23218 }
23219 else
23220 {
23221 it->c = it->char_to_display = ' ';
23222
23223
23224
23225 face = FACE_FROM_ID (it->f, it->face_id);
23226 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23227
23228
23229
23230
23231 if (!(it->glyph_row->reversed_p
23232
23233
23234
23235 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23236 should_keep_end_of_box_run = true;
23237 }
23238 PRODUCE_GLYPHS (it);
23239
23240
23241 if (should_keep_end_of_box_run)
23242 it->end_of_box_run_p = saved_end_of_box_run;
23243 #ifdef HAVE_WINDOW_SYSTEM
23244 if (FRAME_WINDOW_P (it->f))
23245 {
23246
23247
23248
23249 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23250 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23251 if (n == 0)
23252 {
23253 Lisp_Object height, total_height;
23254 int extra_line_spacing = it->extra_line_spacing;
23255 int boff = font->baseline_offset;
23256
23257 if (font->vertical_centering)
23258 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23259
23260 it->object = saved_object;
23261 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23262
23263
23264 height = get_it_property (it, Qline_height);
23265 if (CONSP (height)
23266 && CONSP (XCDR (height))
23267 && NILP (XCDR (XCDR (height))))
23268 {
23269 total_height = XCAR (XCDR (height));
23270 height = XCAR (height);
23271 }
23272 else
23273 total_height = Qnil;
23274 height = calc_line_height_property (it, height, font, boff, true);
23275
23276 if (it->override_ascent >= 0)
23277 {
23278 it->ascent = it->override_ascent;
23279 it->descent = it->override_descent;
23280 boff = it->override_boff;
23281 }
23282 if (EQ (height, Qt))
23283 extra_line_spacing = 0;
23284 else
23285 {
23286 Lisp_Object spacing;
23287
23288 it->phys_ascent = it->ascent;
23289 it->phys_descent = it->descent;
23290 if (!NILP (height)
23291 && XFIXNUM (height) > it->ascent + it->descent)
23292 it->ascent = XFIXNUM (height) - it->descent;
23293
23294 if (!NILP (total_height))
23295 spacing = calc_line_height_property (it, total_height, font,
23296 boff, false);
23297 else
23298 {
23299 spacing = get_it_property (it, Qline_spacing);
23300 spacing = calc_line_height_property (it, spacing, font,
23301 boff, false);
23302 }
23303 if (FIXNUMP (spacing))
23304 {
23305 extra_line_spacing = XFIXNUM (spacing);
23306 if (!NILP (total_height))
23307 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23308 }
23309 }
23310 if (extra_line_spacing > 0)
23311 {
23312 it->descent += extra_line_spacing;
23313 if (extra_line_spacing > it->max_extra_line_spacing)
23314 it->max_extra_line_spacing = extra_line_spacing;
23315 }
23316 it->max_ascent = it->ascent;
23317 it->max_descent = it->descent;
23318
23319 it->glyph_row->height = 0;
23320 }
23321
23322 g->ascent = it->max_ascent;
23323 g->descent = it->max_descent;
23324 }
23325 #endif
23326 it->override_ascent = -1;
23327 it->constrain_row_ascent_descent_p = false;
23328 it->current_x = saved_x;
23329 it->object = saved_object;
23330 it->position = saved_pos;
23331 it->what = saved_what;
23332 it->face_id = saved_face_id;
23333 it->len = saved_len;
23334 it->c = saved_c;
23335 it->char_to_display = saved_char_to_display;
23336 it->end_of_box_run_p = saved_box_end;
23337 return true;
23338 }
23339
23340 return false;
23341 }
23342
23343
23344
23345
23346
23347
23348
23349
23350
23351 static void
23352 extend_face_to_end_of_line (struct it *it)
23353 {
23354 struct frame *f = it->f;
23355
23356
23357
23358
23359
23360
23361 if ((it->current_x >= it->last_visible_x
23362 + (!FRAME_WINDOW_P (f)
23363 && it->glyph_row->reversed_p
23364 && !it->glyph_row->continued_p))
23365
23366
23367 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23368 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23369 return;
23370
23371 specpdl_ref count = SPECPDL_INDEX ();
23372
23373
23374
23375
23376 specbind (Qinhibit_quit, Qt);
23377
23378 struct face *default_face =
23379 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23380 if (!default_face)
23381 return;
23382
23383 const int extend_face_id =
23384 (it->face_id == default_face->id || it->s != NULL)
23385 ? it->face_id
23386 : (it->glyph_row->ends_at_zv_p
23387 ? default_face->id
23388 : face_at_pos (it, LFACE_EXTEND_INDEX));
23389 unbind_to (count, Qnil);
23390
23391
23392
23393
23394 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23395 ? it->saved_face_id
23396 : extend_face_id));
23397
23398 if (FRAME_WINDOW_P (f)
23399 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23400 && face->box == FACE_NO_BOX
23401 && face->underline == FACE_NO_UNDERLINE
23402 && !face->overline_p
23403 && !face->strike_through_p
23404 && face->background == FRAME_BACKGROUND_PIXEL (f)
23405 #ifdef HAVE_WINDOW_SYSTEM
23406 && !face->stipple
23407 #endif
23408 && !it->glyph_row->reversed_p
23409 && !display_fill_column_indicator)
23410 return;
23411
23412
23413
23414 it->glyph_row->fill_line_p = true;
23415
23416 const int orig_face_id = it->face_id;
23417
23418
23419
23420
23421
23422 if (!ASCII_CHAR_P (it->c))
23423 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23424
23425
23426 #ifdef HAVE_WINDOW_SYSTEM
23427 if (FRAME_WINDOW_P (f))
23428 {
23429
23430
23431 if (it->glyph_row->used[TEXT_AREA] == 0)
23432 {
23433 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23434 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23435 it->glyph_row->used[TEXT_AREA] = 1;
23436 }
23437
23438
23439 if (!(it->glyph_row->mode_line_p
23440 || (WINDOWP (f->tab_bar_window)
23441 && it->w == XWINDOW (f->tab_bar_window))
23442 #ifndef HAVE_EXT_TOOL_BAR
23443 || (WINDOWP (f->tool_bar_window)
23444 && it->w == XWINDOW (f->tool_bar_window))
23445 #endif
23446 ))
23447 {
23448 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23449 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23450 {
23451 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23452 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23453 default_face->id;
23454 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23455 }
23456 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23457 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23458 {
23459 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23460 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23461 default_face->id;
23462 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23463 }
23464
23465 struct font *font = (default_face->font
23466 ? default_face->font
23467 : FRAME_FONT (f));
23468
23469 const int char_width = (font->average_width
23470 ? font->average_width
23471 : font->space_width);
23472
23473 const int indicator_column =
23474 fill_column_indicator_column (it, char_width);
23475
23476 const char saved_char = it->char_to_display;
23477 const struct text_pos saved_pos = it->position;
23478 const bool saved_avoid_cursor = it->avoid_cursor_p;
23479 const bool saved_box_start = it->start_of_box_run_p;
23480 Lisp_Object save_object = it->object;
23481 const int saved_face_id = it->face_id;
23482
23483 it->face_id = extend_face_id;
23484 it->avoid_cursor_p = true;
23485 it->object = Qnil;
23486
23487 const int stretch_height = it->ascent + it->descent;
23488 const int stretch_ascent =
23489 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23490
23491 if (indicator_column >= 0
23492 && indicator_column > it->current_x
23493 && indicator_column < it->last_visible_x)
23494 {
23495
23496
23497
23498
23499 const int stretch_width =
23500 indicator_column - it->current_x - char_width;
23501
23502 clear_position (it);
23503
23504
23505
23506 if (stretch_width > 0)
23507 {
23508 append_stretch_glyph (it, Qnil, stretch_width,
23509 stretch_height, stretch_ascent);
23510 }
23511
23512
23513
23514 if (it->current_x < indicator_column)
23515 {
23516 const int save_face_id = it->face_id;
23517 const int save_ascent = it->ascent;
23518 const int save_descent = it->descent;
23519 it->char_to_display
23520 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23521 it->face_id
23522 = merge_faces (it->w, Qfill_column_indicator,
23523 0, extend_face_id);
23524 PRODUCE_GLYPHS (it);
23525 it->face_id = save_face_id;
23526 it->ascent = save_ascent;
23527 it->descent = save_descent;
23528 }
23529 }
23530
23531
23532
23533 if (!it->glyph_row->reversed_p)
23534 {
23535 const int stretch_width = it->last_visible_x - it->current_x;
23536
23537 if (stretch_width > 0)
23538 {
23539 clear_position (it);
23540 append_stretch_glyph (it, Qnil, stretch_width,
23541 stretch_height, stretch_ascent);
23542 }
23543 }
23544
23545 it->char_to_display = saved_char;
23546 it->position = saved_pos;
23547 it->avoid_cursor_p = saved_avoid_cursor;
23548 it->start_of_box_run_p = saved_box_start;
23549 it->object = save_object;
23550 it->face_id = saved_face_id;
23551 }
23552 if (it->glyph_row->reversed_p)
23553 {
23554
23555
23556
23557
23558
23559 struct font *font = face->font ? face->font : FRAME_FONT (f);
23560 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23561 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23562 struct glyph *g;
23563 int row_width, stretch_ascent, stretch_width;
23564 struct text_pos saved_pos;
23565 int saved_face_id;
23566 bool saved_avoid_cursor, saved_box_start;
23567
23568 for (row_width = 0, g = row_start; g < row_end; g++)
23569 row_width += g->pixel_width;
23570
23571
23572
23573
23574 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23575 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23576 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23577 stretch_width = window_box_width (it->w, TEXT_AREA);
23578 else
23579 stretch_width = it->last_visible_x - it->first_visible_x;
23580 stretch_width -= row_width;
23581
23582 if (stretch_width > 0)
23583 {
23584 stretch_ascent =
23585 (((it->ascent + it->descent)
23586 * FONT_BASE (font)) / FONT_HEIGHT (font));
23587 saved_pos = it->position;
23588 clear_position (it);
23589 saved_avoid_cursor = it->avoid_cursor_p;
23590 it->avoid_cursor_p = true;
23591 saved_face_id = it->face_id;
23592 saved_box_start = it->start_of_box_run_p;
23593
23594
23595
23596 it->face_id = (it->glyph_row->ends_at_zv_p ?
23597 default_face->id : face->id);
23598
23599 it->start_of_box_run_p = false;
23600 append_stretch_glyph (it, Qnil, stretch_width,
23601 it->ascent + it->descent, stretch_ascent);
23602 it->position = saved_pos;
23603 it->avoid_cursor_p = saved_avoid_cursor;
23604 it->face_id = saved_face_id;
23605 it->start_of_box_run_p = saved_box_start;
23606 }
23607
23608
23609
23610
23611 if (stretch_width < 0)
23612 it->glyph_row->x = stretch_width;
23613 }
23614 it->face_id = orig_face_id;
23615 }
23616 else
23617 #endif
23618 {
23619
23620 int saved_x = it->current_x;
23621 struct text_pos saved_pos = it->position;
23622 Lisp_Object saved_object = it->object;;
23623 enum display_element_type saved_what = it->what;
23624
23625 it->what = IT_CHARACTER;
23626 clear_position (it);
23627 it->object = Qnil;
23628 it->c = it->char_to_display = ' ';
23629 it->len = 1;
23630
23631 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23632 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23633 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23634 && !it->glyph_row->mode_line_p
23635 && face->background != FRAME_BACKGROUND_PIXEL (f))
23636 {
23637 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23638 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23639
23640 for (it->current_x = 0; g < e; g++)
23641 it->current_x += g->pixel_width;
23642
23643 it->area = LEFT_MARGIN_AREA;
23644 it->face_id = default_face->id;
23645 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23646 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23647 && g < it->glyph_row->glyphs[TEXT_AREA])
23648 {
23649 PRODUCE_GLYPHS (it);
23650
23651
23652 it->current_x += it->pixel_width;
23653 g++;
23654 }
23655
23656 it->current_x = saved_x;
23657 it->area = TEXT_AREA;
23658 }
23659
23660
23661
23662
23663 it->face_id = (it->glyph_row->ends_at_zv_p ?
23664 default_face->id : face->id);
23665
23666
23667
23668
23669
23670 it->current_x = it->glyph_row->used[TEXT_AREA];
23671
23672
23673
23674
23675
23676
23677
23678
23679 const int indicator_column =
23680 fill_column_indicator_column (it, 1) - it->first_visible_x;
23681
23682
23683 while (it->current_x <= it->last_visible_x)
23684 {
23685 if (it->current_x != indicator_column)
23686 PRODUCE_GLYPHS (it);
23687 else
23688 {
23689 int saved_face_id = it->face_id;
23690 it->face_id
23691 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23692 it->c = it->char_to_display
23693 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23694
23695 PRODUCE_GLYPHS (it);
23696
23697 it->face_id = saved_face_id;
23698 it->c = it->char_to_display = ' ';
23699 }
23700 }
23701
23702 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23703 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23704 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23705 && !it->glyph_row->mode_line_p
23706 && face->background != FRAME_BACKGROUND_PIXEL (f))
23707 {
23708 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23709 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23710
23711 for ( ; g < e; g++)
23712 it->current_x += g->pixel_width;
23713
23714 it->area = RIGHT_MARGIN_AREA;
23715 it->face_id = default_face->id;
23716 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23717 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23718 && g < it->glyph_row->glyphs[LAST_AREA])
23719 {
23720 PRODUCE_GLYPHS (it);
23721 it->current_x += it->pixel_width;
23722 g++;
23723 }
23724
23725 it->area = TEXT_AREA;
23726 }
23727
23728
23729
23730 it->current_x = saved_x;
23731 it->object = saved_object;
23732 it->position = saved_pos;
23733 it->what = saved_what;
23734 it->face_id = orig_face_id;
23735 }
23736 }
23737
23738
23739
23740
23741
23742 static bool
23743 trailing_whitespace_p (ptrdiff_t charpos)
23744 {
23745 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23746 int c = 0;
23747
23748 while (bytepos < ZV_BYTE
23749 && (c = FETCH_BYTE (bytepos),
23750 c == ' ' || c == '\t'))
23751 ++bytepos;
23752
23753 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23754 {
23755 if (bytepos != PT_BYTE)
23756 return true;
23757 }
23758 return false;
23759 }
23760
23761
23762
23763
23764 static void
23765 highlight_trailing_whitespace (struct it *it)
23766 {
23767 struct glyph_row *row = it->glyph_row;
23768 int used = row->used[TEXT_AREA];
23769
23770 if (used)
23771 {
23772 struct glyph *start = row->glyphs[TEXT_AREA];
23773 struct glyph *glyph = start + used - 1;
23774
23775 if (row->reversed_p)
23776 {
23777
23778
23779 glyph = start;
23780 start = row->glyphs[TEXT_AREA] + used - 1;
23781 }
23782
23783
23784
23785
23786
23787 if (!row->reversed_p)
23788 {
23789 while (glyph >= start
23790 && (glyph->type == CHAR_GLYPH
23791 || glyph->type == STRETCH_GLYPH)
23792 && NILP (glyph->object))
23793 --glyph;
23794 }
23795 else
23796 {
23797 while (glyph <= start
23798 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
23799 && NILP (glyph->object))
23800 ++glyph;
23801 }
23802
23803
23804
23805
23806 if ((row->reversed_p ? glyph <= start : glyph >= start)
23807 && BUFFERP (glyph->object)
23808 && (glyph->type == STRETCH_GLYPH
23809 || (glyph->type == CHAR_GLYPH
23810 && glyph->u.ch == ' '))
23811 && trailing_whitespace_p (glyph->charpos))
23812 {
23813 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
23814 if (face_id < 0)
23815 return;
23816
23817 if (!row->reversed_p)
23818 {
23819 while (glyph >= start
23820 && BUFFERP (glyph->object)
23821 && (glyph->type == STRETCH_GLYPH
23822 || (glyph->type == CHAR_GLYPH
23823 && glyph->u.ch == ' ')))
23824 (glyph--)->face_id = face_id;
23825 }
23826 else
23827 {
23828 while (glyph <= start
23829 && BUFFERP (glyph->object)
23830 && (glyph->type == STRETCH_GLYPH
23831 || (glyph->type == CHAR_GLYPH
23832 && glyph->u.ch == ' ')))
23833 (glyph++)->face_id = face_id;
23834 }
23835 }
23836 }
23837 }
23838
23839
23840
23841
23842
23843 static bool
23844 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
23845 {
23846 bool result = true;
23847
23848 if (charpos == CHARPOS (row->end.pos)
23849 || charpos == MATRIX_ROW_END_CHARPOS (row))
23850 {
23851
23852
23853
23854
23855
23856
23857
23858
23859 if (CHARPOS (row->end.string_pos) >= 0)
23860 {
23861 if (row->continued_p)
23862 result = true;
23863 else
23864 {
23865
23866 struct glyph *beg = row->glyphs[TEXT_AREA];
23867 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
23868 struct glyph *glyph;
23869
23870 result = false;
23871 for (glyph = end; glyph >= beg; --glyph)
23872 if (STRINGP (glyph->object))
23873 {
23874 Lisp_Object prop
23875 = Fget_char_property (make_fixnum (charpos),
23876 Qdisplay, Qnil);
23877 result =
23878 (!NILP (prop)
23879 && display_prop_string_p (prop, glyph->object));
23880
23881
23882
23883 if (!result)
23884 {
23885 Lisp_Object s = glyph->object;
23886
23887 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
23888 {
23889 ptrdiff_t gpos = glyph->charpos;
23890
23891 if (!NILP (Fget_char_property (make_fixnum (gpos),
23892 Qcursor, s)))
23893 {
23894 result = true;
23895 break;
23896 }
23897 }
23898 }
23899 break;
23900 }
23901 }
23902 }
23903 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
23904 {
23905
23906
23907
23908
23909 if (!row->ends_in_ellipsis_p)
23910 result = row->continued_p;
23911 else
23912
23913
23914
23915
23916 result = false;
23917 }
23918
23919
23920 else
23921 result = row->ends_at_zv_p;
23922 }
23923
23924 return result;
23925 }
23926
23927
23928
23929
23930 static bool
23931 cursor_row_p (struct glyph_row *row)
23932 {
23933 return row_for_charpos_p (row, PT);
23934 }
23935
23936
23937
23938
23939
23940
23941
23942
23943 static bool
23944 push_prefix_prop (struct it *it, Lisp_Object prop)
23945 {
23946 struct text_pos pos =
23947 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
23948
23949 eassert (it->method == GET_FROM_BUFFER
23950 || it->method == GET_FROM_DISPLAY_VECTOR
23951 || it->method == GET_FROM_STRING
23952 || it->method == GET_FROM_IMAGE);
23953
23954
23955
23956
23957
23958 push_it (it, &pos);
23959
23960 if (STRINGP (prop))
23961 {
23962 if (SCHARS (prop) == 0)
23963 {
23964 pop_it (it);
23965 return false;
23966 }
23967
23968 it->string = prop;
23969 it->string_from_prefix_prop_p = true;
23970 it->multibyte_p = STRING_MULTIBYTE (it->string);
23971 it->current.overlay_string_index = -1;
23972 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
23973 it->end_charpos = it->string_nchars = SCHARS (it->string);
23974 it->method = GET_FROM_STRING;
23975 it->stop_charpos = 0;
23976 it->prev_stop = 0;
23977 it->base_level_stop = 0;
23978 it->cmp_it.id = -1;
23979
23980
23981
23982 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
23983 it->paragraph_embedding = it->bidi_it.paragraph_dir;
23984 else
23985 it->paragraph_embedding = L2R;
23986
23987
23988 if (it->bidi_p)
23989 {
23990 it->bidi_it.string.lstring = it->string;
23991 it->bidi_it.string.s = NULL;
23992 it->bidi_it.string.schars = it->end_charpos;
23993 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
23994 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
23995 it->bidi_it.string.unibyte = !it->multibyte_p;
23996 it->bidi_it.w = it->w;
23997 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
23998 }
23999 }
24000 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
24001 {
24002 it->method = GET_FROM_STRETCH;
24003 it->object = prop;
24004 }
24005 #ifdef HAVE_WINDOW_SYSTEM
24006 else if (IMAGEP (prop))
24007 {
24008 it->what = IT_IMAGE;
24009 it->image_id = lookup_image (it->f, prop, it->face_id);
24010 it->method = GET_FROM_IMAGE;
24011 }
24012 #endif
24013 else
24014 {
24015 pop_it (it);
24016 return false;
24017 }
24018
24019 return true;
24020 }
24021
24022
24023
24024 static Lisp_Object
24025 get_it_property (struct it *it, Lisp_Object prop)
24026 {
24027 Lisp_Object position, object = it->object;
24028
24029 if (STRINGP (object))
24030 position = make_fixnum (IT_STRING_CHARPOS (*it));
24031 else if (BUFFERP (object))
24032 {
24033 position = make_fixnum (IT_CHARPOS (*it));
24034 object = it->window;
24035 }
24036 else
24037 return Qnil;
24038
24039 return Fget_char_property (position, prop, object);
24040 }
24041
24042
24043
24044
24045 static Lisp_Object
24046 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24047 {
24048 Lisp_Object prefix = get_it_property (it, prop);
24049
24050
24051
24052 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24053 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24054 it->w->contents);
24055 return prefix;
24056 }
24057
24058
24059
24060 static void
24061 handle_line_prefix (struct it *it)
24062 {
24063 Lisp_Object prefix;
24064
24065 if (it->continuation_lines_width > 0)
24066 {
24067 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24068 if (NILP (prefix))
24069 prefix = Vwrap_prefix;
24070 }
24071 else
24072 {
24073 prefix = get_line_prefix_it_property (it, Qline_prefix);
24074 if (NILP (prefix))
24075 prefix = Vline_prefix;
24076 }
24077 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24078 {
24079
24080
24081
24082 it->line_wrap = TRUNCATE;
24083 it->avoid_cursor_p = true;
24084 }
24085 }
24086
24087
24088
24089
24090
24091
24092
24093 static void
24094 unproduce_glyphs (struct it *it, int n)
24095 {
24096 struct glyph *glyph, *end;
24097
24098 eassert (it->glyph_row);
24099 eassert (it->glyph_row->reversed_p);
24100 eassert (it->area == TEXT_AREA);
24101 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24102
24103 if (n > it->glyph_row->used[TEXT_AREA])
24104 n = it->glyph_row->used[TEXT_AREA];
24105 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24106 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24107 for ( ; glyph < end; glyph++)
24108 glyph[-n] = *glyph;
24109 }
24110
24111
24112
24113 static void
24114 find_row_edges (struct it *it, struct glyph_row *row,
24115 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24116 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24117 {
24118
24119
24120
24121
24122
24123 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24124 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24125 else
24126
24127
24128
24129 row->minpos = row->start.pos;
24130 if (max_pos <= 0)
24131 {
24132 max_pos = CHARPOS (it->current.pos);
24133 max_bpos = BYTEPOS (it->current.pos);
24134 }
24135
24136
24137
24138
24139
24140
24141
24142
24143
24144
24145
24146
24147
24148
24149
24150
24151
24152 if (row->ends_at_zv_p)
24153 row->maxpos = it->current.pos;
24154 else if (row->used[TEXT_AREA])
24155 {
24156 bool seen_this_string = false;
24157 struct glyph_row *r1 = row - 1;
24158
24159
24160 if (STRINGP (it->object)
24161
24162 && row > it->w->desired_matrix->rows
24163
24164 && !r1->mode_line_p
24165
24166 && r1->ends_in_newline_from_string_p)
24167 {
24168 struct glyph *start, *end;
24169
24170
24171
24172
24173
24174 if (!r1->reversed_p)
24175 {
24176 start = r1->glyphs[TEXT_AREA];
24177 end = start + r1->used[TEXT_AREA];
24178
24179 while (end > start
24180 && NILP ((end - 1)->object)
24181 && (end - 1)->charpos <= 0)
24182 --end;
24183 if (end > start)
24184 {
24185 if (EQ ((end - 1)->object, it->object))
24186 seen_this_string = true;
24187 }
24188 else
24189
24190
24191
24192
24193
24194 seen_this_string = true;
24195 }
24196 else
24197 {
24198 end = r1->glyphs[TEXT_AREA] - 1;
24199 start = end + r1->used[TEXT_AREA];
24200 while (end < start
24201 && NILP ((end + 1)->object)
24202 && (end + 1)->charpos <= 0)
24203 ++end;
24204 if (end < start)
24205 {
24206 if (EQ ((end + 1)->object, it->object))
24207 seen_this_string = true;
24208 }
24209 else
24210 seen_this_string = true;
24211 }
24212 }
24213
24214
24215
24216 if (row->ends_in_newline_from_string_p && !seen_this_string)
24217 {
24218
24219
24220
24221
24222
24223
24224
24225
24226 if (CHARPOS (row->end.pos) > max_pos)
24227 inc_both (&max_pos, &max_bpos);
24228 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24229 }
24230 else if (CHARPOS (it->eol_pos) > 0)
24231 SET_TEXT_POS (row->maxpos,
24232 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24233 else if (row->continued_p)
24234 {
24235
24236
24237
24238
24239
24240
24241 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24242 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24243 else
24244 {
24245 inc_both (&max_pos, &max_bpos);
24246 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24247 }
24248 }
24249 else if (row->truncated_on_right_p)
24250
24251
24252
24253 row->maxpos = it->current.pos;
24254 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24255
24256 row->maxpos = row->minpos;
24257 else
24258 emacs_abort ();
24259 }
24260 else
24261 row->maxpos = it->current.pos;
24262 }
24263
24264
24265
24266 static ptrdiff_t
24267 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24268 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24269 {
24270 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24271 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24272
24273 ptrdiff_t val;
24274 specpdl_ref pdl_count = SPECPDL_INDEX ();
24275 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24276 labeled_restrictions_remove_in_current_buffer ();
24277 Fwiden ();
24278 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24279 unbind_to (pdl_count, Qnil);
24280 return val;
24281 }
24282
24283
24284
24285 static ptrdiff_t
24286 display_count_lines_visually (struct it *it)
24287 {
24288 struct it tem_it;
24289 ptrdiff_t to;
24290 struct text_pos from;
24291
24292
24293
24294
24295
24296
24297 if (it->lnum_bytepos > 0)
24298 return it->lnum + 1;
24299 else
24300 {
24301 specpdl_ref count = SPECPDL_INDEX ();
24302
24303 if (IT_CHARPOS (*it) <= PT)
24304 {
24305 from = it->current.pos;
24306 to = PT;
24307 }
24308 else
24309 {
24310 SET_TEXT_POS (from, PT, PT_BYTE);
24311 to = IT_CHARPOS (*it);
24312 }
24313
24314
24315
24316 specbind (Qdisplay_line_numbers, Qrelative);
24317 start_display (&tem_it, it->w, from);
24318
24319
24320
24321
24322 move_it_to (&tem_it, to, -1,
24323 tem_it.last_visible_y
24324 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24325 -1, MOVE_TO_POS | MOVE_TO_Y);
24326 unbind_to (count, Qnil);
24327 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24328 }
24329 }
24330
24331
24332
24333
24334 static void
24335 maybe_produce_line_number (struct it *it)
24336 {
24337 ptrdiff_t last_line = it->lnum;
24338 ptrdiff_t start_from, bytepos;
24339 ptrdiff_t this_line;
24340 bool first_time = false;
24341 ptrdiff_t beg_byte;
24342 ptrdiff_t z_byte;
24343 bool line_numbers_wide;
24344 void *itdata = bidi_shelve_cache ();
24345
24346 if (display_line_numbers_offset
24347 && !display_line_numbers_widen
24348 && !EQ (Vdisplay_line_numbers, Qvisual)
24349 && !EQ (Vdisplay_line_numbers, Qrelative))
24350 line_numbers_wide = true;
24351 else
24352 line_numbers_wide = display_line_numbers_widen;
24353
24354 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24355 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24356
24357 if (EQ (Vdisplay_line_numbers, Qvisual))
24358 this_line = display_count_lines_visually (it);
24359 else
24360 {
24361 if (!last_line)
24362 {
24363
24364 if (it->w->base_line_number > 0
24365 && it->w->base_line_pos > 0
24366 && it->w->base_line_pos <= IT_CHARPOS (*it)
24367
24368
24369
24370
24371 && !(line_numbers_wide
24372 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24373 && !current_buffer->clip_changed)
24374 {
24375 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24376 last_line = it->w->base_line_number - 1;
24377 }
24378 else
24379 start_from = beg_byte;
24380 if (!it->lnum_bytepos)
24381 first_time = true;
24382 }
24383 else
24384 start_from = it->lnum_bytepos;
24385
24386
24387
24388
24389 if (!(beg_byte <= start_from && start_from <= z_byte))
24390 {
24391 last_line = 0;
24392 start_from = beg_byte;
24393 }
24394
24395 this_line =
24396 last_line + display_count_lines_logically (start_from,
24397 IT_BYTEPOS (*it),
24398 IT_CHARPOS (*it), &bytepos);
24399 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24400 eassert (bytepos == IT_BYTEPOS (*it));
24401 }
24402
24403
24404 if (this_line != last_line || !it->lnum_bytepos)
24405 {
24406 it->lnum = this_line;
24407 it->lnum_bytepos = IT_BYTEPOS (*it);
24408 }
24409
24410
24411 struct it tem_it;
24412 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24413 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24414 ptrdiff_t lnum_offset = -1;
24415 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24416 int current_lnum_face_id
24417 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24418
24419
24420 bool save_free_realized_faces = inhibit_free_realized_faces;
24421 inhibit_free_realized_faces = true;
24422
24423 if ((EQ (Vdisplay_line_numbers, Qrelative)
24424 || EQ (Vdisplay_line_numbers, Qvisual)
24425 || lnum_face_id != current_lnum_face_id)
24426 && !it->pt_lnum)
24427 {
24428 ptrdiff_t ignored;
24429 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24430 it->pt_lnum =
24431 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24432 PT, &ignored);
24433 else
24434 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24435 &ignored);
24436 }
24437
24438 if (!it->lnum_width)
24439 {
24440 if (FIXNATP (Vdisplay_line_numbers_width))
24441 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24442
24443
24444
24445 ptrdiff_t max_lnum;
24446
24447 if (NILP (Vdisplay_line_numbers_current_absolute)
24448 && (EQ (Vdisplay_line_numbers, Qrelative)
24449 || EQ (Vdisplay_line_numbers, Qvisual)))
24450
24451
24452 max_lnum = it->w->desired_matrix->nrows - 2;
24453 else if (EQ (Vdisplay_line_numbers, Qvisual))
24454 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24455 else
24456 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24457 max_lnum = max (1, max_lnum);
24458 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24459 eassert (it->lnum_width > 0);
24460 }
24461 if (EQ (Vdisplay_line_numbers, Qrelative))
24462 lnum_offset = it->pt_lnum;
24463 else if (EQ (Vdisplay_line_numbers, Qvisual))
24464 lnum_offset = 0;
24465 else if (display_line_numbers_offset)
24466 lnum_offset -= display_line_numbers_offset;
24467
24468
24469
24470 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24471 if ((EQ (Vdisplay_line_numbers, Qrelative)
24472 || EQ (Vdisplay_line_numbers, Qvisual))
24473 && lnum_to_display == 0
24474 && !NILP (Vdisplay_line_numbers_current_absolute))
24475 lnum_to_display = it->pt_lnum + 1;
24476
24477
24478
24479
24480
24481 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24482 strcat (lnum_buf, " ");
24483
24484
24485 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24486
24487 DEFAULT_FACE_ID);
24488 scratch_glyph_row.reversed_p = false;
24489 scratch_glyph_row.used[TEXT_AREA] = 0;
24490 SET_TEXT_POS (tem_it.position, 0, 0);
24491 tem_it.avoid_cursor_p = true;
24492 tem_it.bidi_p = true;
24493 tem_it.bidi_it.type = WEAK_EN;
24494
24495
24496
24497 tem_it.bidi_it.resolved_level = 2;
24498
24499
24500
24501 int width_limit =
24502 tem_it.last_visible_x - tem_it.first_visible_x
24503 - 3 * FRAME_COLUMN_WIDTH (it->f);
24504
24505 tem_it.face_id = lnum_face_id;
24506
24507
24508 if (lnum_face_id != current_lnum_face_id
24509 && (EQ (Vdisplay_line_numbers, Qvisual)
24510 ? this_line == 0
24511 : this_line == it->pt_lnum)
24512 && it->what != IT_EOB)
24513 tem_it.face_id = current_lnum_face_id;
24514 else if (!beyond_zv)
24515 {
24516 if (display_line_numbers_major_tick > 0
24517 && (lnum_to_display % display_line_numbers_major_tick == 0))
24518 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24519 0, DEFAULT_FACE_ID);
24520 else if (display_line_numbers_minor_tick > 0
24521 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24522 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24523 0, DEFAULT_FACE_ID);
24524 }
24525
24526
24527 for (const char *p = lnum_buf; *p; p++)
24528 {
24529
24530
24531 if (beyond_zv
24532
24533 || (!EQ (Vdisplay_line_numbers, Qvisual)
24534 && (it->continuation_lines_width > 0
24535 || (this_line == last_line && !first_time))))
24536 tem_it.c = tem_it.char_to_display = ' ';
24537 else
24538 tem_it.c = tem_it.char_to_display = *p;
24539 tem_it.len = 1;
24540
24541 SET_TEXT_POS (tem_it.position, -1, -1);
24542 PRODUCE_GLYPHS (&tem_it);
24543
24544
24545
24546 if (tem_it.current_x >= width_limit)
24547 {
24548 it->lnum_width = 0;
24549 it->lnum_pixel_width = 0;
24550 bidi_unshelve_cache (itdata, false);
24551 inhibit_free_realized_faces = save_free_realized_faces;
24552 return;
24553 }
24554 }
24555
24556 inhibit_free_realized_faces = save_free_realized_faces;
24557
24558
24559 it->lnum_pixel_width = tem_it.current_x;
24560
24561 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24562 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24563 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24564 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24565
24566 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24567
24568 for ( ; g < e; g++)
24569 {
24570 it->current_x += g->pixel_width;
24571
24572
24573
24574 if (it->current_x > it->first_visible_x)
24575 it->hpos++;
24576 if (p)
24577 {
24578 *p++ = *g;
24579 (*u)++;
24580 }
24581 }
24582
24583
24584
24585
24586 if (!beyond_zv)
24587 {
24588 if (it->glyph_row)
24589 {
24590 struct glyph_row *row = it->glyph_row;
24591
24592 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24593 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24594 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24595 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24596 tem_it.max_phys_descent);
24597 }
24598 else
24599 {
24600 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24601 it->max_descent = max (it->max_descent, tem_it.max_descent);
24602 it->max_phys_ascent = max (it->max_phys_ascent,
24603 tem_it.max_phys_ascent);
24604 it->max_phys_descent = max (it->max_phys_descent,
24605 tem_it.max_phys_descent);
24606 }
24607 }
24608
24609 it->line_number_produced_p = true;
24610
24611 bidi_unshelve_cache (itdata, false);
24612 }
24613
24614
24615
24616 static bool
24617 should_produce_line_number (struct it *it)
24618 {
24619 if (NILP (Vdisplay_line_numbers))
24620 return false;
24621
24622
24623 if (MINI_WINDOW_P (it->w))
24624 return false;
24625
24626 #ifdef HAVE_WINDOW_SYSTEM
24627
24628 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24629 return false;
24630 #endif
24631
24632
24633
24634
24635
24636 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24637 Qdisplay_line_numbers_disable,
24638 it->window);
24639
24640
24641
24642 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24643 val = disable_line_numbers_overlay_at_eob ();
24644 return NILP (val) ? true : false;
24645 }
24646
24647
24648
24649
24650
24651 static bool
24652 row_text_area_empty (struct glyph_row *row)
24653 {
24654 if (!row->reversed_p)
24655 {
24656 for (struct glyph *g = row->glyphs[TEXT_AREA];
24657 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24658 g++)
24659 if (!NILP (g->object) || g->charpos > 0)
24660 return false;
24661 }
24662 else
24663 {
24664 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24665 g > row->glyphs[TEXT_AREA];
24666 g--)
24667 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24668 return false;
24669 }
24670
24671 return true;
24672 }
24673
24674
24675
24676
24677
24678
24679
24680
24681 static bool
24682 display_line (struct it *it, int cursor_vpos)
24683 {
24684 struct glyph_row *row = it->glyph_row;
24685 Lisp_Object overlay_arrow_string;
24686 struct it wrap_it;
24687 void *wrap_data = NULL;
24688 bool may_wrap = false;
24689 int wrap_x UNINIT;
24690 int wrap_row_used = -1;
24691 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24692 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24693 int wrap_row_extra_line_spacing UNINIT;
24694 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24695 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24696 int cvpos;
24697 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24698 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24699 bool pending_handle_line_prefix = false;
24700 int tab_line = window_wants_tab_line (it->w);
24701 int header_line = window_wants_header_line (it->w);
24702 bool hscroll_this_line = (cursor_vpos >= 0
24703 && it->vpos == cursor_vpos - tab_line - header_line
24704 && hscrolling_current_line_p (it->w));
24705 int first_visible_x = it->first_visible_x;
24706 int last_visible_x = it->last_visible_x;
24707 int x_incr = 0;
24708
24709
24710 eassert (it->hpos == 0 && it->current_x == 0);
24711
24712 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24713 >= it->w->desired_matrix->nrows)
24714 {
24715 it->w->nrows_scale_factor++;
24716 it->f->fonts_changed = true;
24717 return false;
24718 }
24719
24720
24721 prepare_desired_row (it->w, row, false);
24722
24723 row->y = it->current_y;
24724 row->start = it->start;
24725 row->continuation_lines_width = it->continuation_lines_width;
24726 row->displays_text_p = true;
24727 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24728 it->starts_in_middle_of_char_p = false;
24729 it->stretch_adjust = 0;
24730 it->line_number_produced_p = false;
24731
24732
24733
24734
24735 if (hscroll_this_line)
24736 x_incr =
24737 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24738 * FRAME_COLUMN_WIDTH (it->f);
24739
24740 bool line_number_needed = should_produce_line_number (it);
24741
24742
24743
24744
24745 if (it->current_x < it->first_visible_x + x_incr)
24746 {
24747 enum move_it_result move_result;
24748
24749 this_line_min_pos = row->start.pos;
24750 if (hscroll_this_line)
24751 {
24752 it->first_visible_x += x_incr;
24753 it->last_visible_x += x_incr;
24754 }
24755 if (current_buffer->long_line_optimizations_p
24756 && it->line_wrap == TRUNCATE
24757 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24758 {
24759
24760
24761
24762
24763 ptrdiff_t chars_to_skip =
24764 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24765 move_result = fast_move_it_horizontally (it, chars_to_skip);
24766
24767 if (move_result == MOVE_X_REACHED)
24768 it->current_x = it->first_visible_x;
24769 else
24770 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24771 }
24772 else
24773 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
24774 MOVE_TO_POS | MOVE_TO_X);
24775
24776
24777
24778
24779
24780
24781 if (it->current_x < it->first_visible_x
24782 && (move_result == MOVE_NEWLINE_OR_CR
24783 || move_result == MOVE_POS_MATCH_OR_ZV))
24784 it->current_x = it->first_visible_x;
24785
24786
24787
24788 it->line_number_produced_p = false;
24789
24790
24791
24792
24793
24794
24795
24796
24797 min_pos = CHARPOS (this_line_min_pos);
24798 min_bpos = BYTEPOS (this_line_min_pos);
24799
24800
24801 if (line_number_needed)
24802 maybe_produce_line_number (it);
24803 }
24804 else if (it->area == TEXT_AREA)
24805 {
24806
24807 if (line_number_needed)
24808 maybe_produce_line_number (it);
24809
24810
24811
24812 handle_line_prefix (it);
24813 }
24814 else
24815 {
24816
24817
24818
24819
24820
24821
24822
24823 pending_handle_line_prefix = true;
24824 }
24825
24826
24827
24828 row->ascent = it->max_ascent;
24829 row->height = it->max_ascent + it->max_descent;
24830 row->phys_ascent = it->max_phys_ascent;
24831 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
24832 row->extra_line_spacing = it->max_extra_line_spacing;
24833
24834
24835 #define RECORD_MAX_MIN_POS(IT) \
24836 do \
24837 { \
24838 bool composition_p \
24839 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
24840 ptrdiff_t current_pos = \
24841 composition_p ? (IT)->cmp_it.charpos \
24842 : IT_CHARPOS (*(IT)); \
24843 ptrdiff_t current_bpos = \
24844 composition_p ? CHAR_TO_BYTE (current_pos) \
24845 : IT_BYTEPOS (*(IT)); \
24846 if (current_pos < min_pos) \
24847 { \
24848 min_pos = current_pos; \
24849 min_bpos = current_bpos; \
24850 } \
24851 if (IT_CHARPOS (*it) > max_pos) \
24852 { \
24853 max_pos = IT_CHARPOS (*it); \
24854 max_bpos = IT_BYTEPOS (*it); \
24855 } \
24856 } \
24857 while (false)
24858
24859
24860
24861 while (true)
24862 {
24863 int n_glyphs_before, hpos_before, x_before;
24864 int x, nglyphs;
24865 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
24866
24867
24868
24869 if (!get_next_display_element (it))
24870 {
24871 bool row_has_glyphs = false;
24872
24873
24874
24875
24876 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
24877 row->exact_window_width_line_p = true;
24878 else if ((append_space_for_newline (it, true)
24879 && row->used[TEXT_AREA] == 1)
24880 || row->used[TEXT_AREA] == 0
24881 || (row_has_glyphs = row_text_area_empty (row)))
24882 {
24883 row->glyphs[TEXT_AREA]->charpos = -1;
24884
24885
24886 if (!row_has_glyphs)
24887 row->displays_text_p = false;
24888
24889 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
24890 && (!MINI_WINDOW_P (it->w)))
24891 row->indicate_empty_line_p = true;
24892 }
24893
24894 it->continuation_lines_width = 0;
24895
24896
24897
24898
24899 it->font_height = Qnil;
24900 it->voffset = 0;
24901 row->ends_at_zv_p = true;
24902
24903
24904
24905
24906
24907
24908
24909
24910 if (row->reversed_p
24911 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
24912 != DEFAULT_FACE_ID)
24913 extend_face_to_end_of_line (it);
24914 break;
24915 }
24916
24917
24918
24919 n_glyphs_before = row->used[TEXT_AREA];
24920 x = it->current_x;
24921
24922
24923
24924 if (it->line_wrap != TRUNCATE)
24925 {
24926 ascent = it->max_ascent;
24927 descent = it->max_descent;
24928 phys_ascent = it->max_phys_ascent;
24929 phys_descent = it->max_phys_descent;
24930
24931 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
24932 {
24933 bool next_may_wrap = may_wrap;
24934
24935 if (char_can_wrap_after (it))
24936 next_may_wrap = true;
24937 else
24938 next_may_wrap = false;
24939
24940 if (may_wrap && char_can_wrap_before (it))
24941 {
24942 SAVE_IT (wrap_it, *it, wrap_data);
24943 wrap_x = x;
24944 wrap_row_used = row->used[TEXT_AREA];
24945 wrap_row_ascent = row->ascent;
24946 wrap_row_height = row->height;
24947 wrap_row_phys_ascent = row->phys_ascent;
24948 wrap_row_phys_height = row->phys_height;
24949 wrap_row_extra_line_spacing = row->extra_line_spacing;
24950 wrap_row_min_pos = min_pos;
24951 wrap_row_min_bpos = min_bpos;
24952 wrap_row_max_pos = max_pos;
24953 wrap_row_max_bpos = max_bpos;
24954 }
24955
24956 may_wrap = next_may_wrap;
24957 }
24958 }
24959
24960 PRODUCE_GLYPHS (it);
24961
24962
24963
24964 if (it->area != TEXT_AREA)
24965 {
24966 row->ascent = max (row->ascent, it->max_ascent);
24967 row->height = max (row->height, it->max_ascent + it->max_descent);
24968 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
24969 row->phys_height = max (row->phys_height,
24970 it->max_phys_ascent + it->max_phys_descent);
24971 row->extra_line_spacing = max (row->extra_line_spacing,
24972 it->max_extra_line_spacing);
24973 set_iterator_to_next (it, true);
24974
24975
24976
24977 if (it->area == TEXT_AREA && pending_handle_line_prefix)
24978 {
24979
24980 if (line_number_needed)
24981 maybe_produce_line_number (it);
24982
24983 pending_handle_line_prefix = false;
24984 handle_line_prefix (it);
24985 }
24986 continue;
24987 }
24988
24989
24990
24991
24992
24993
24994
24995
24996
24997
24998 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
24999 hpos_before = it->hpos;
25000 x_before = x;
25001
25002 if (
25003 nglyphs > 0
25004
25005 && it->current_x < it->last_visible_x)
25006 {
25007 it->hpos += nglyphs;
25008 row->ascent = max (row->ascent, it->max_ascent);
25009 row->height = max (row->height, it->max_ascent + it->max_descent);
25010 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25011 row->phys_height = max (row->phys_height,
25012 it->max_phys_ascent + it->max_phys_descent);
25013 row->extra_line_spacing = max (row->extra_line_spacing,
25014 it->max_extra_line_spacing);
25015 if (it->current_x - it->pixel_width < it->first_visible_x
25016
25017
25018
25019 && !line_number_needed
25020
25021
25022
25023
25024 && !row->reversed_p)
25025 row->x = x - it->first_visible_x;
25026
25027
25028 if (it->bidi_p)
25029 RECORD_MAX_MIN_POS (it);
25030 }
25031 else
25032 {
25033 int i, new_x;
25034 struct glyph *glyph;
25035
25036 for (i = 0; i < nglyphs; ++i, x = new_x)
25037 {
25038
25039
25040
25041 if (!row->reversed_p)
25042 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25043 else
25044 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25045 new_x = x + glyph->pixel_width;
25046
25047 if (
25048 it->line_wrap != TRUNCATE
25049 && (
25050 new_x > it->last_visible_x
25051
25052 || (new_x == it->last_visible_x
25053 && FRAME_WINDOW_P (it->f)
25054 && (row->reversed_p
25055 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25056 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25057 {
25058
25059
25060 if (it->hpos == 0
25061 || (new_x == it->last_visible_x
25062 && FRAME_WINDOW_P (it->f)
25063 && (row->reversed_p
25064 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25065 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25066 {
25067
25068
25069
25070
25071 row->continued_p = true;
25072 it->current_x = new_x;
25073 it->continuation_lines_width += new_x;
25074 ++it->hpos;
25075 if (i == nglyphs - 1)
25076 {
25077
25078
25079 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25080 && wrap_row_used > 0
25081
25082
25083
25084
25085
25086
25087
25088
25089
25090
25091 && (!may_wrap || !char_can_wrap_before (it)))
25092 goto back_to_wrap;
25093
25094
25095
25096
25097 if (it->bidi_p)
25098 RECORD_MAX_MIN_POS (it);
25099 set_iterator_to_next (it, true);
25100 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25101 {
25102 if (!get_next_display_element (it))
25103 {
25104 row->exact_window_width_line_p = true;
25105 it->continuation_lines_width = 0;
25106 it->font_height = Qnil;
25107 it->voffset = 0;
25108 row->continued_p = false;
25109 row->ends_at_zv_p = true;
25110 }
25111 else if (ITERATOR_AT_END_OF_LINE_P (it))
25112 {
25113 row->continued_p = false;
25114 row->exact_window_width_line_p = true;
25115 }
25116
25117
25118 else if (wrap_row_used > 0
25119
25120
25121
25122
25123
25124
25125
25126
25127
25128 && (!may_wrap || !char_can_wrap_before (it)))
25129 goto back_to_wrap;
25130
25131 }
25132 }
25133 else if (it->bidi_p)
25134 RECORD_MAX_MIN_POS (it);
25135 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25136 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25137 extend_face_to_end_of_line (it);
25138 }
25139 else if (CHAR_GLYPH_PADDING_P (*glyph)
25140 && !FRAME_WINDOW_P (it->f))
25141 {
25142
25143
25144
25145 if (row->reversed_p)
25146 unproduce_glyphs (it, row->used[TEXT_AREA]
25147 - n_glyphs_before);
25148 row->used[TEXT_AREA] = n_glyphs_before;
25149
25150
25151
25152 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25153 < row->glyphs[1 + TEXT_AREA])
25154 produce_special_glyphs (it, IT_CONTINUATION);
25155
25156 row->continued_p = true;
25157 it->current_x = x_before;
25158 it->continuation_lines_width += x_before;
25159
25160
25161
25162 it->max_ascent = ascent;
25163 it->max_descent = descent;
25164 it->max_phys_ascent = phys_ascent;
25165 it->max_phys_descent = phys_descent;
25166 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25167 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25168 extend_face_to_end_of_line (it);
25169 }
25170 else if (wrap_row_used > 0)
25171 {
25172 back_to_wrap:
25173 if (row->reversed_p)
25174 unproduce_glyphs (it,
25175 row->used[TEXT_AREA] - wrap_row_used);
25176 RESTORE_IT (it, &wrap_it, wrap_data);
25177 it->continuation_lines_width += wrap_x;
25178 row->used[TEXT_AREA] = wrap_row_used;
25179 row->ascent = wrap_row_ascent;
25180 row->height = wrap_row_height;
25181 row->phys_ascent = wrap_row_phys_ascent;
25182 row->phys_height = wrap_row_phys_height;
25183 row->extra_line_spacing = wrap_row_extra_line_spacing;
25184 min_pos = wrap_row_min_pos;
25185 min_bpos = wrap_row_min_bpos;
25186 max_pos = wrap_row_max_pos;
25187 max_bpos = wrap_row_max_bpos;
25188 row->continued_p = true;
25189 row->ends_at_zv_p = false;
25190 row->exact_window_width_line_p = false;
25191
25192
25193
25194 extend_face_to_end_of_line (it);
25195 }
25196 else if ((it->what == IT_CHARACTER
25197 || it->what == IT_STRETCH
25198 || it->what == IT_COMPOSITION)
25199 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25200 {
25201
25202
25203
25204
25205
25206 if ((row->reversed_p
25207 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25208 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25209 produce_special_glyphs (it, IT_CONTINUATION);
25210 it->continuation_lines_width += it->last_visible_x;
25211 row->ends_in_middle_of_char_p = true;
25212 row->continued_p = true;
25213 glyph->pixel_width = it->last_visible_x - x;
25214 it->starts_in_middle_of_char_p = true;
25215 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25216 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25217 extend_face_to_end_of_line (it);
25218 }
25219 else
25220 {
25221
25222
25223
25224 if (row->reversed_p)
25225 unproduce_glyphs (it, row->used[TEXT_AREA]
25226 - (n_glyphs_before + i));
25227 row->used[TEXT_AREA] = n_glyphs_before + i;
25228
25229
25230 it->current_x = x_before;
25231 it->continuation_lines_width += x;
25232 if (!FRAME_WINDOW_P (it->f)
25233 || (row->reversed_p
25234 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25235 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25236 produce_special_glyphs (it, IT_CONTINUATION);
25237 row->continued_p = true;
25238
25239 extend_face_to_end_of_line (it);
25240
25241 if (nglyphs > 1 && i > 0)
25242 {
25243 row->ends_in_middle_of_char_p = true;
25244 it->starts_in_middle_of_char_p = true;
25245 }
25246
25247
25248
25249 it->max_ascent = ascent;
25250 it->max_descent = descent;
25251 it->max_phys_ascent = phys_ascent;
25252 it->max_phys_descent = phys_descent;
25253 }
25254
25255 break;
25256 }
25257 else if (new_x > it->first_visible_x)
25258 {
25259
25260 ++it->hpos;
25261
25262
25263
25264
25265 if (it->bidi_p)
25266 RECORD_MAX_MIN_POS (it);
25267
25268 if (x < it->first_visible_x && !row->reversed_p
25269 && !line_number_needed)
25270
25271
25272
25273
25274
25275
25276 row->x = x - it->first_visible_x;
25277
25278
25279
25280
25281
25282
25283 if (row->reversed_p
25284 && new_x > it->last_visible_x
25285 && !line_number_needed
25286 && !(it->line_wrap == TRUNCATE
25287 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25288 {
25289 eassert (FRAME_WINDOW_P (it->f));
25290 row->x = it->last_visible_x - new_x;
25291 }
25292 }
25293 else
25294 {
25295
25296
25297
25298
25299
25300 eassert (it->first_visible_x <= it->last_visible_x);
25301 }
25302 }
25303
25304
25305 if (it->bidi_p && nglyphs == 0)
25306 RECORD_MAX_MIN_POS (it);
25307
25308 row->ascent = max (row->ascent, it->max_ascent);
25309 row->height = max (row->height, it->max_ascent + it->max_descent);
25310 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25311 row->phys_height = max (row->phys_height,
25312 it->max_phys_ascent + it->max_phys_descent);
25313 row->extra_line_spacing = max (row->extra_line_spacing,
25314 it->max_extra_line_spacing);
25315
25316
25317 if (row->continued_p || row->ends_at_zv_p)
25318 break;
25319 }
25320
25321 at_end_of_line:
25322
25323
25324
25325 if (ITERATOR_AT_END_OF_LINE_P (it))
25326 {
25327 int used_before = row->used[TEXT_AREA];
25328
25329 row->ends_in_newline_from_string_p = STRINGP (it->object);
25330
25331
25332
25333 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25334 append_space_for_newline (it, false);
25335
25336
25337 extend_face_to_end_of_line (it);
25338
25339
25340 if (used_before == 0)
25341 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25342
25343
25344
25345 it->eol_pos = it->current.pos;
25346
25347
25348 set_iterator_to_next (it, true);
25349 it->continuation_lines_width = 0;
25350 break;
25351 }
25352
25353
25354
25355
25356
25357
25358
25359
25360 bool overwide_wrap_prefix =
25361 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25362 && it->sp > 0 && it->method == GET_FROM_STRETCH
25363 && it->current_x >= it->last_visible_x
25364 && it->continuation_lines_width > 0
25365 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25366
25367
25368
25369 if (!overwide_wrap_prefix)
25370 set_iterator_to_next (it, true);
25371
25372
25373
25374 if (it->line_wrap == TRUNCATE
25375 && ((FRAME_WINDOW_P (it->f)
25376
25377
25378
25379
25380 && ((row->reversed_p
25381 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25382 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25383 || it->what == IT_IMAGE))
25384 ? (it->current_x >= it->last_visible_x)
25385 : (it->current_x > it->last_visible_x)))
25386 {
25387
25388 if (!FRAME_WINDOW_P (it->f)
25389 || (row->reversed_p
25390 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25391 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25392 {
25393 int i, n;
25394
25395 if (!row->reversed_p)
25396 {
25397 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25398 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25399 break;
25400 }
25401 else
25402 {
25403 for (i = 0; i < row->used[TEXT_AREA]; i++)
25404 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25405 break;
25406
25407
25408
25409
25410
25411 unproduce_glyphs (it, i + 1);
25412
25413 i = row->used[TEXT_AREA] - (i + 1);
25414 }
25415
25416
25417
25418
25419 if (it->current_x > it->last_visible_x)
25420 {
25421 it->current_x = x_before;
25422 if (!FRAME_WINDOW_P (it->f))
25423 {
25424 for (n = row->used[TEXT_AREA]; i < n; ++i)
25425 {
25426 row->used[TEXT_AREA] = i;
25427 produce_special_glyphs (it, IT_TRUNCATION);
25428 }
25429 }
25430 else
25431 {
25432 row->used[TEXT_AREA] = i;
25433 produce_special_glyphs (it, IT_TRUNCATION);
25434 }
25435 it->hpos = hpos_before;
25436 }
25437 }
25438 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25439 {
25440
25441 if (!get_next_display_element (it))
25442 {
25443 it->continuation_lines_width = 0;
25444 it->font_height = Qnil;
25445 it->voffset = 0;
25446 row->ends_at_zv_p = true;
25447 row->exact_window_width_line_p = true;
25448 break;
25449 }
25450 if (ITERATOR_AT_END_OF_LINE_P (it))
25451 {
25452 row->exact_window_width_line_p = true;
25453 goto at_end_of_line;
25454 }
25455 it->current_x = x_before;
25456 it->hpos = hpos_before;
25457 }
25458
25459 row->truncated_on_right_p = true;
25460 it->continuation_lines_width = 0;
25461 reseat_at_next_visible_line_start (it, false);
25462
25463
25464
25465
25466 if (IT_BYTEPOS (*it) > BEG_BYTE)
25467 row->ends_at_zv_p =
25468 IT_BYTEPOS (*it) >= ZV_BYTE
25469 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25470 else
25471 row->ends_at_zv_p = false;
25472 break;
25473 }
25474 }
25475
25476 if (wrap_data)
25477 bidi_unshelve_cache (wrap_data, true);
25478
25479
25480
25481 if (it->first_visible_x
25482 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25483 {
25484 if (!FRAME_WINDOW_P (it->f)
25485 || (((row->reversed_p
25486 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25487 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25488
25489
25490 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25491 insert_left_trunc_glyphs (it);
25492 row->truncated_on_left_p = true;
25493 }
25494
25495
25496
25497
25498
25499
25500 row->end = it->current;
25501 if (!it->bidi_p)
25502 {
25503 row->minpos = row->start.pos;
25504 row->maxpos = row->end.pos;
25505 }
25506 else
25507 {
25508
25509
25510
25511
25512 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25513 }
25514
25515
25516
25517
25518
25519 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25520 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25521 !NILP (overlay_arrow_string)))
25522 {
25523
25524 if (STRINGP (overlay_arrow_string))
25525 {
25526 struct glyph_row *arrow_row
25527 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25528 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25529 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25530 struct glyph *p = row->glyphs[TEXT_AREA];
25531 struct glyph *p2, *end;
25532
25533
25534 while (glyph < arrow_end)
25535 *p++ = *glyph++;
25536
25537
25538 p2 = p;
25539 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25540 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25541 ++p2;
25542 if (p2 > p)
25543 {
25544 while (p2 < end)
25545 *p++ = *p2++;
25546 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25547 }
25548 }
25549 else
25550 {
25551 eassert (FIXNUMP (overlay_arrow_string));
25552 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25553 }
25554 overlay_arrow_seen = true;
25555 }
25556
25557
25558 if (!NILP (Vshow_trailing_whitespace))
25559 highlight_trailing_whitespace (it);
25560
25561
25562 compute_line_metrics (it);
25563
25564
25565
25566
25567
25568
25569
25570 row->ends_in_ellipsis_p
25571 = (it->method == GET_FROM_DISPLAY_VECTOR
25572 && it->ellipsis_p);
25573
25574
25575 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25576 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25577 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25578 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25579
25580 it->left_user_fringe_bitmap = 0;
25581 it->left_user_fringe_face_id = 0;
25582 it->right_user_fringe_bitmap = 0;
25583 it->right_user_fringe_face_id = 0;
25584
25585
25586
25587
25588
25589
25590 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25591 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25592 row->redraw_fringe_bitmaps_p = true;
25593
25594
25595 cvpos = it->w->cursor.vpos;
25596 if ((cvpos < 0
25597
25598
25599
25600
25601
25602
25603
25604
25605 || (it->bidi_p
25606 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25607 && PT >= MATRIX_ROW_START_CHARPOS (row)
25608 && PT <= MATRIX_ROW_END_CHARPOS (row)
25609 && cursor_row_p (row))
25610 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25611
25612
25613
25614
25615
25616 it->current_x = it->hpos = 0;
25617 it->current_y += row->height;
25618
25619
25620 if (hscroll_this_line)
25621 {
25622 it->first_visible_x = first_visible_x;
25623 it->last_visible_x = last_visible_x;
25624 }
25625 SET_TEXT_POS (it->eol_pos, 0, 0);
25626 ++it->vpos;
25627 ++it->glyph_row;
25628
25629
25630
25631
25632 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25633 it->glyph_row->reversed_p = row->reversed_p;
25634 it->start = row->end;
25635 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25636
25637 #undef RECORD_MAX_MIN_POS
25638 }
25639
25640 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25641 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25642 doc:
25643
25644
25645
25646
25647
25648
25649
25650
25651 )
25652 (Lisp_Object buffer)
25653 {
25654 struct buffer *buf = current_buffer;
25655 struct buffer *old = buf;
25656
25657 if (! NILP (buffer))
25658 {
25659 CHECK_BUFFER (buffer);
25660 buf = XBUFFER (buffer);
25661 }
25662
25663 if (NILP (BVAR (buf, bidi_display_reordering))
25664 || NILP (BVAR (buf, enable_multibyte_characters))
25665
25666
25667 || redisplay__inhibit_bidi)
25668 return Qleft_to_right;
25669 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25670 return BVAR (buf, bidi_paragraph_direction);
25671 else
25672 {
25673
25674
25675
25676 struct bidi_it itb;
25677 ptrdiff_t pos = BUF_PT (buf);
25678 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25679 int c;
25680 void *itb_data = bidi_shelve_cache ();
25681
25682 set_buffer_temp (buf);
25683
25684
25685
25686
25687
25688 if (pos >= ZV && pos > BEGV)
25689 dec_both (&pos, &bytepos);
25690 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25691 if (fast_looking_at (trailing_white_space,
25692 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25693 {
25694 while ((c = FETCH_BYTE (bytepos)) == '\n'
25695 || c == ' ' || c == '\t' || c == '\f')
25696 {
25697 if (bytepos <= BEGV_BYTE)
25698 break;
25699 bytepos--;
25700 pos--;
25701 }
25702 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25703 bytepos--;
25704 }
25705 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25706 itb.paragraph_dir = NEUTRAL_DIR;
25707 itb.string.s = NULL;
25708 itb.string.lstring = Qnil;
25709 itb.string.bufpos = 0;
25710 itb.string.from_disp_str = false;
25711 itb.string.unibyte = false;
25712
25713
25714
25715 itb.w = NULL;
25716 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25717 bidi_unshelve_cache (itb_data, false);
25718 set_buffer_temp (old);
25719 switch (itb.paragraph_dir)
25720 {
25721 case L2R:
25722 return Qleft_to_right;
25723 break;
25724 case R2L:
25725 return Qright_to_left;
25726 break;
25727 default:
25728 emacs_abort ();
25729 }
25730 }
25731 }
25732
25733 DEFUN ("bidi-find-overridden-directionality",
25734 Fbidi_find_overridden_directionality,
25735 Sbidi_find_overridden_directionality, 3, 4, 0,
25736 doc:
25737
25738
25739
25740
25741
25742
25743
25744
25745
25746
25747
25748
25749
25750
25751
25752
25753
25754
25755
25756
25757
25758
25759
25760
25761
25762
25763
25764
25765
25766
25767
25768
25769
25770
25771
25772
25773 )
25774 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
25775 {
25776 struct buffer *buf = current_buffer;
25777 struct buffer *old = buf;
25778 struct window *w = NULL;
25779 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
25780 struct bidi_it itb;
25781 ptrdiff_t from_pos, to_pos, from_bpos;
25782 void *itb_data;
25783
25784 if (!NILP (object))
25785 {
25786 if (BUFFERP (object))
25787 buf = XBUFFER (object);
25788 else if (WINDOWP (object))
25789 {
25790 w = decode_live_window (object);
25791 buf = XBUFFER (w->contents);
25792 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
25793 }
25794 else
25795 CHECK_STRING (object);
25796 }
25797
25798 if (STRINGP (object))
25799 {
25800
25801
25802 if (!STRING_MULTIBYTE (object)
25803
25804
25805
25806 || redisplay__inhibit_bidi)
25807 return Qnil;
25808
25809 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
25810 if (from_pos >= SCHARS (object))
25811 return Qnil;
25812
25813
25814 itb_data = bidi_shelve_cache ();
25815 itb.paragraph_dir = NEUTRAL_DIR;
25816 itb.string.lstring = object;
25817 itb.string.s = NULL;
25818 itb.string.schars = SCHARS (object);
25819 itb.string.bufpos = 0;
25820 itb.string.from_disp_str = false;
25821 itb.string.unibyte = false;
25822 itb.w = w;
25823 bidi_init_it (0, 0, frame_window_p, &itb);
25824 }
25825 else
25826 {
25827
25828
25829 if (NILP (BVAR (buf, bidi_display_reordering))
25830 || NILP (BVAR (buf, enable_multibyte_characters))
25831
25832
25833
25834 || redisplay__inhibit_bidi)
25835 return Qnil;
25836
25837 set_buffer_temp (buf);
25838 validate_region (&from, &to);
25839 from_pos = XFIXNUM (from);
25840 to_pos = XFIXNUM (to);
25841 if (from_pos >= ZV)
25842 return Qnil;
25843
25844
25845 itb_data = bidi_shelve_cache ();
25846 from_bpos = CHAR_TO_BYTE (from_pos);
25847 if (from_pos == BEGV)
25848 {
25849 itb.charpos = BEGV;
25850 itb.bytepos = BEGV_BYTE;
25851 }
25852 else if (FETCH_BYTE (from_bpos - 1) == '\n')
25853 {
25854 itb.charpos = from_pos;
25855 itb.bytepos = from_bpos;
25856 }
25857 else
25858 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
25859 -1, &itb.bytepos);
25860 itb.paragraph_dir = NEUTRAL_DIR;
25861 itb.string.s = NULL;
25862 itb.string.lstring = Qnil;
25863 itb.string.bufpos = 0;
25864 itb.string.from_disp_str = false;
25865 itb.string.unibyte = false;
25866 itb.w = w;
25867 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
25868 }
25869
25870 ptrdiff_t found;
25871 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
25872 do {
25873 bidi_paragraph_init (bdir, &itb, false);
25874 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
25875 ;
25876 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
25877
25878 bidi_unshelve_cache (itb_data, false);
25879 set_buffer_temp (old);
25880
25881 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
25882 }
25883
25884 DEFUN ("move-point-visually", Fmove_point_visually,
25885 Smove_point_visually, 1, 1, 0,
25886 doc:
25887
25888
25889
25890 )
25891 (Lisp_Object direction)
25892 {
25893 struct window *w = XWINDOW (selected_window);
25894 struct buffer *b = XBUFFER (w->contents);
25895 struct glyph_row *row;
25896 int dir;
25897 Lisp_Object paragraph_dir;
25898
25899 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
25900 (!(ROW)->continued_p \
25901 && NILP ((GLYPH)->object) \
25902 && (GLYPH)->type == CHAR_GLYPH \
25903 && (GLYPH)->u.ch == ' ' \
25904 && (GLYPH)->charpos >= 0 \
25905 && !(GLYPH)->avoid_cursor_p)
25906
25907 CHECK_FIXNUM (direction);
25908 dir = XFIXNUM (direction);
25909 if (dir > 0)
25910 dir = 1;
25911 else
25912 dir = -1;
25913
25914
25915
25916
25917 if (w->window_end_valid
25918 && !windows_or_buffers_changed
25919 && b
25920 && !b->clip_changed
25921 && !b->prevent_redisplay_optimizations_p
25922 && !window_outdated (w)
25923
25924
25925
25926 && w->last_point == BUF_PT (b)
25927 && w->cursor.vpos >= 0
25928 && w->cursor.vpos < w->current_matrix->nrows
25929 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
25930 {
25931 struct glyph *g = row->glyphs[TEXT_AREA];
25932 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
25933 struct glyph *gpt = g + w->cursor.hpos;
25934
25935 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
25936 {
25937 if (BUFFERP (g->object) && g->charpos != PT)
25938 {
25939 SET_PT (g->charpos);
25940 w->cursor.vpos = -1;
25941 return make_fixnum (PT);
25942 }
25943 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
25944 {
25945 ptrdiff_t new_pos;
25946
25947 if (BUFFERP (gpt->object))
25948 {
25949 new_pos = PT;
25950 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
25951 new_pos += (row->reversed_p ? -dir : dir);
25952 else
25953 new_pos -= (row->reversed_p ? -dir : dir);
25954 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
25955
25956
25957 if (new_pos == PT)
25958 break;
25959 }
25960 else if (BUFFERP (g->object))
25961 new_pos = g->charpos;
25962 else
25963 break;
25964 SET_PT (new_pos);
25965 w->cursor.vpos = -1;
25966 return make_fixnum (PT);
25967 }
25968 else if (ROW_GLYPH_NEWLINE_P (row, g))
25969 {
25970
25971
25972
25973 if (g->charpos > 0)
25974 SET_PT (g->charpos);
25975 else if (row->ends_at_zv_p && PT != ZV)
25976 SET_PT (ZV);
25977 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
25978 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
25979 else
25980 break;
25981 w->cursor.vpos = -1;
25982 return make_fixnum (PT);
25983 }
25984 }
25985 if (g == e || NILP (g->object))
25986 {
25987 if (row->truncated_on_left_p || row->truncated_on_right_p)
25988 goto simulate_display;
25989 if (!row->reversed_p)
25990 row += dir;
25991 else
25992 row -= dir;
25993 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
25994 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
25995 goto simulate_display;
25996
25997 if (dir > 0)
25998 {
25999 if (row->reversed_p && !row->continued_p)
26000 {
26001 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26002 w->cursor.vpos = -1;
26003 return make_fixnum (PT);
26004 }
26005 g = row->glyphs[TEXT_AREA];
26006 e = g + row->used[TEXT_AREA];
26007 for ( ; g < e; g++)
26008 {
26009 if (BUFFERP (g->object)
26010
26011
26012
26013 || ROW_GLYPH_NEWLINE_P (row, g)
26014
26015
26016 || (row->ends_at_zv_p
26017 && !row->reversed_p
26018 && NILP (g->object)
26019 && g->type == CHAR_GLYPH
26020 && g->u.ch == ' '))
26021 {
26022 if (g->charpos > 0)
26023 SET_PT (g->charpos);
26024 else if (!row->reversed_p
26025 && row->ends_at_zv_p
26026 && PT != ZV)
26027 SET_PT (ZV);
26028 else
26029 continue;
26030 w->cursor.vpos = -1;
26031 return make_fixnum (PT);
26032 }
26033 }
26034 }
26035 else
26036 {
26037 if (!row->reversed_p && !row->continued_p)
26038 {
26039 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26040 w->cursor.vpos = -1;
26041 return make_fixnum (PT);
26042 }
26043 e = row->glyphs[TEXT_AREA];
26044 g = e + row->used[TEXT_AREA] - 1;
26045 for ( ; g >= e; g--)
26046 {
26047 if (BUFFERP (g->object)
26048 || (ROW_GLYPH_NEWLINE_P (row, g)
26049 && g->charpos > 0)
26050
26051
26052
26053 || g->type == STRETCH_GLYPH
26054 || (row->ends_at_zv_p
26055 && row->reversed_p
26056 && NILP (g->object)
26057 && g->type == CHAR_GLYPH
26058 && g->u.ch == ' '))
26059 {
26060 if (g->charpos > 0)
26061 SET_PT (g->charpos);
26062 else if (row->reversed_p
26063 && row->ends_at_zv_p
26064 && PT != ZV)
26065 SET_PT (ZV);
26066 else
26067 continue;
26068 w->cursor.vpos = -1;
26069 return make_fixnum (PT);
26070 }
26071 }
26072 }
26073 }
26074 }
26075
26076 simulate_display:
26077
26078
26079
26080
26081 if (b)
26082 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26083 else
26084 paragraph_dir = Qleft_to_right;
26085 if (EQ (paragraph_dir, Qright_to_left))
26086 dir = -dir;
26087 if (PT <= BEGV && dir < 0)
26088 xsignal0 (Qbeginning_of_buffer);
26089 else if (PT >= ZV && dir > 0)
26090 xsignal0 (Qend_of_buffer);
26091 else
26092 {
26093 struct text_pos pt;
26094 struct it it;
26095 int pt_x, target_x, pixel_width, pt_vpos;
26096 bool at_eol_p;
26097 bool overshoot_expected = false;
26098 bool target_is_eol_p = false;
26099 void *itdata = bidi_shelve_cache ();
26100
26101
26102 SET_TEXT_POS (pt, PT, PT_BYTE);
26103 start_display (&it, w, pt);
26104
26105
26106
26107
26108
26109
26110 if (it.line_wrap == TRUNCATE)
26111 it.last_visible_x = DISP_INFINITY;
26112
26113 if (it.cmp_it.id < 0
26114 && it.method == GET_FROM_STRING
26115 && it.area == TEXT_AREA
26116 && it.string_from_display_prop_p
26117 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26118 overshoot_expected = true;
26119
26120
26121
26122
26123
26124 reseat:
26125 reseat_at_previous_visible_line_start (&it);
26126 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26127 if (IT_CHARPOS (it) != PT)
26128 {
26129 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26130 -1, -1, -1, MOVE_TO_POS);
26131
26132
26133
26134 if (it.method == GET_FROM_DISPLAY_VECTOR
26135 && it.current.dpvec_index > 0
26136 && !overshoot_expected)
26137 {
26138 overshoot_expected = true;
26139 goto reseat;
26140 }
26141 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26142 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26143 }
26144 pt_x = it.current_x;
26145 pt_vpos = it.vpos;
26146 if (dir > 0 || overshoot_expected)
26147 {
26148 struct glyph_row *row = it.glyph_row;
26149
26150
26151
26152
26153 if (pt_x == 0)
26154 get_next_display_element (&it);
26155 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26156 it.glyph_row = NULL;
26157 PRODUCE_GLYPHS (&it);
26158 it.glyph_row = row;
26159
26160
26161
26162 it.current_x = pt_x;
26163 }
26164 else
26165 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26166 pixel_width = it.pixel_width;
26167 if (overshoot_expected && at_eol_p)
26168 pixel_width = 0;
26169 else if (pixel_width <= 0)
26170 pixel_width = 1;
26171
26172
26173
26174
26175 if (overshoot_expected)
26176 {
26177 if (it.bidi_p)
26178 pt_x += pixel_width * it.bidi_it.scan_dir;
26179 else
26180 pt_x += pixel_width;
26181 }
26182
26183
26184
26185
26186
26187
26188
26189 if (dir > 0)
26190 target_x = pt_x + pixel_width;
26191 else
26192 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26193
26194
26195
26196
26197
26198 if (dir < 0)
26199 {
26200 if (pt_x > 0)
26201 {
26202 start_display (&it, w, pt);
26203 if (it.line_wrap == TRUNCATE)
26204 it.last_visible_x = DISP_INFINITY;
26205 reseat_at_previous_visible_line_start (&it);
26206 it.current_x = it.current_y = it.hpos = 0;
26207 if (pt_vpos != 0)
26208 move_it_by_lines (&it, pt_vpos);
26209 }
26210 else
26211 {
26212 move_it_by_lines (&it, -1);
26213 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26214 target_is_eol_p = true;
26215
26216
26217
26218
26219
26220
26221
26222
26223
26224
26225 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26226 {
26227 void *it_data = NULL;
26228 struct it it2;
26229
26230 SAVE_IT (it2, it, it_data);
26231 move_it_in_display_line_to (&it, ZV, target_x,
26232 MOVE_TO_POS | MOVE_TO_X);
26233
26234
26235 if (it.current_x != target_x)
26236 target_x = it.current_x - 1;
26237 RESTORE_IT (&it, &it2, it_data);
26238 }
26239 }
26240 }
26241 else
26242 {
26243 if (at_eol_p
26244 || (target_x >= it.last_visible_x
26245 && it.line_wrap != TRUNCATE))
26246 {
26247 if (pt_x > 0)
26248 move_it_by_lines (&it, 0);
26249 move_it_by_lines (&it, 1);
26250 target_x = 0;
26251 }
26252 }
26253
26254
26255
26256
26257
26258
26259
26260 if (FRAME_WINDOW_P (it.f) && dir < 0)
26261 {
26262 struct text_pos new_pos;
26263 enum move_it_result rc = MOVE_X_REACHED;
26264
26265 if (it.current_x == 0)
26266 get_next_display_element (&it);
26267 if (it.what == IT_COMPOSITION)
26268 {
26269 new_pos.charpos = it.cmp_it.charpos;
26270 new_pos.bytepos = -1;
26271 }
26272 else
26273 new_pos = it.current.pos;
26274
26275 while (it.current_x + it.pixel_width <= target_x
26276 && (rc == MOVE_X_REACHED
26277
26278
26279
26280 || (it.line_wrap == WORD_WRAP
26281 && rc == MOVE_POS_MATCH_OR_ZV)))
26282 {
26283 int new_x = it.current_x + it.pixel_width;
26284
26285
26286
26287
26288
26289
26290
26291 if (it.what == IT_COMPOSITION)
26292 {
26293 new_pos.charpos = it.cmp_it.charpos;
26294 new_pos.bytepos = -1;
26295 }
26296 else
26297 new_pos = it.current.pos;
26298 if (new_x == it.current_x)
26299 new_x++;
26300 rc = move_it_in_display_line_to (&it, ZV, new_x,
26301 MOVE_TO_POS | MOVE_TO_X);
26302 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26303 break;
26304 }
26305
26306
26307 if (new_pos.bytepos == -1)
26308 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26309 it.current.pos = new_pos;
26310 }
26311 else if (it.current_x != target_x)
26312 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26313
26314
26315
26316 if (dir > 0)
26317 {
26318 while (IT_CHARPOS (it) == PT)
26319 {
26320 set_iterator_to_next (&it, false);
26321 if (!get_next_display_element (&it))
26322 break;
26323 }
26324 }
26325
26326
26327 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26328 bidi_unshelve_cache (itdata, false);
26329 }
26330
26331 return make_fixnum (PT);
26332
26333 #undef ROW_GLYPH_NEWLINE_P
26334 }
26335
26336 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26337 Sbidi_resolved_levels, 0, 1, 0,
26338 doc:
26339
26340
26341
26342
26343
26344
26345
26346
26347
26348
26349
26350
26351
26352
26353
26354
26355
26356
26357
26358
26359
26360
26361
26362
26363
26364 )
26365 (Lisp_Object vpos)
26366 {
26367 struct window *w = XWINDOW (selected_window);
26368 struct buffer *b = XBUFFER (w->contents);
26369 int nrow;
26370 struct glyph_row *row;
26371
26372 if (NILP (vpos))
26373 {
26374 int d1, d2, d3, d4, d5;
26375
26376 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26377 }
26378 else
26379 {
26380 CHECK_FIXNUM (vpos);
26381 nrow = XFIXNUM (vpos);
26382 }
26383
26384
26385 if (w->window_end_valid
26386 && !windows_or_buffers_changed
26387 && b
26388 && !b->clip_changed
26389 && !b->prevent_redisplay_optimizations_p
26390 && !window_outdated (w)
26391 && nrow >= 0
26392 && nrow < w->current_matrix->nrows
26393 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26394 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26395 {
26396 struct glyph *g, *e, *g1;
26397 int nglyphs, i;
26398 Lisp_Object levels;
26399
26400 if (!row->reversed_p)
26401 {
26402 g = g1 = row->glyphs[TEXT_AREA];
26403 e = g + row->used[TEXT_AREA];
26404
26405
26406
26407 while (g < e
26408 && NILP (g->object)
26409 && g->charpos < 0)
26410 g++;
26411 g1 = g;
26412
26413
26414 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26415 nglyphs++;
26416
26417
26418 levels = make_uninit_vector (nglyphs);
26419 for (i = 0; g1 < g; i++, g1++)
26420 ASET (levels, i, make_fixnum (g1->resolved_level));
26421 }
26422 else
26423 {
26424 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26425 e = row->glyphs[TEXT_AREA] - 1;
26426 while (g > e
26427 && NILP (g->object)
26428 && g->charpos < 0)
26429 g--;
26430 g1 = g;
26431 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26432 nglyphs++;
26433 levels = make_uninit_vector (nglyphs);
26434 for (i = 0; g1 > g; i++, g1--)
26435 ASET (levels, i, make_fixnum (g1->resolved_level));
26436 }
26437 return levels;
26438 }
26439 else
26440 return Qnil;
26441 }
26442
26443
26444
26445
26446
26447
26448
26449
26450
26451
26452
26453
26454
26455
26456
26457
26458
26459 static void
26460 display_menu_bar (struct window *w)
26461 {
26462 struct frame *f = XFRAME (WINDOW_FRAME (w));
26463 struct it it;
26464 Lisp_Object items;
26465 int i;
26466
26467
26468 #ifdef HAVE_NTGUI
26469 if (FRAME_W32_P (f))
26470 return;
26471 #endif
26472 #if defined (HAVE_PGTK)
26473 if (FRAME_PGTK_P (f))
26474 return;
26475 #endif
26476
26477 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26478 if (FRAME_X_P (f))
26479 return;
26480 #endif
26481
26482 #ifdef HAVE_NS
26483 if (FRAME_NS_P (f))
26484 return;
26485 #endif
26486
26487 #ifdef HAVE_HAIKU
26488 if (FRAME_HAIKU_P (f))
26489 return;
26490 #endif
26491
26492 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26493 eassert (!FRAME_WINDOW_P (f));
26494 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26495 it.first_visible_x = 0;
26496 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26497 #elif defined (HAVE_X_WINDOWS)
26498 struct window *menu_window = NULL;
26499 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
26500
26501 if (FRAME_WINDOW_P (f))
26502 {
26503
26504
26505 menu_window = XWINDOW (f->menu_bar_window);
26506 init_iterator (&it, menu_window, -1, -1,
26507 menu_window->desired_matrix->rows,
26508 MENU_FACE_ID);
26509 }
26510 else
26511 #endif
26512 {
26513
26514
26515 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26516 MENU_FACE_ID);
26517 it.first_visible_x = 0;
26518 it.last_visible_x = FRAME_COLS (f);
26519 }
26520
26521
26522
26523
26524 it.paragraph_embedding = L2R;
26525
26526
26527 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26528 {
26529 struct glyph_row *row = it.glyph_row + i;
26530 clear_glyph_row (row);
26531 row->enabled_p = true;
26532 row->full_width_p = true;
26533 row->reversed_p = false;
26534 }
26535
26536
26537 items = FRAME_MENU_BAR_ITEMS (it.f);
26538 for (i = 0; i < ASIZE (items); i += 4)
26539 {
26540 Lisp_Object string;
26541
26542
26543 string = AREF (items, i + 1);
26544 if (NILP (string))
26545 break;
26546
26547
26548 ASET (items, i + 3, make_fixnum (it.hpos));
26549
26550
26551 if (it.current_x < it.last_visible_x)
26552 display_string (NULL, string, Qnil, 0, 0, &it,
26553 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26554 }
26555
26556
26557 if (it.current_x < it.last_visible_x)
26558 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26559
26560
26561 compute_line_metrics (&it);
26562 it.glyph_row->full_width_p = true;
26563 it.glyph_row->continued_p = false;
26564 it.glyph_row->truncated_on_left_p = false;
26565 it.glyph_row->truncated_on_right_p = false;
26566
26567 #if defined (HAVE_X_WINDOWS) && !defined (USE_X_TOOLKIT) && !defined (USE_GTK)
26568
26569 extend_face_to_end_of_line (&it);
26570 if (face->box != FACE_NO_BOX)
26571 {
26572 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26573 + it.glyph_row->used[TEXT_AREA] - 1);
26574 int box_thickness = face->box_vertical_line_width;
26575 last->right_box_line_p = true;
26576
26577
26578
26579
26580
26581
26582 if (box_thickness > 0)
26583 last->pixel_width += max (0, (box_thickness
26584 - (it.current_x - it.last_visible_x)));
26585 }
26586
26587
26588
26589 if (FRAME_WINDOW_P (it.f) && menu_window)
26590 {
26591 struct glyph_row *row;
26592 int delta_height;
26593
26594 row = it.glyph_row;
26595 delta_height
26596 = ((row->y + row->height)
26597 - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
26598
26599 if (delta_height != 0)
26600 {
26601 FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
26602 adjust_frame_size (it.f, -1, -1, 3, false, Qmenu_bar_lines);
26603 }
26604 }
26605 #endif
26606 }
26607
26608
26609 static void
26610 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26611 {
26612 struct glyph *pointers[1 + LAST_AREA];
26613 int to_used = to->used[TEXT_AREA];
26614
26615
26616 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26617
26618
26619 *to = *from;
26620
26621
26622 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26623
26624
26625 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26626 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26627
26628
26629
26630 if (to_used > from->used[TEXT_AREA])
26631 fill_up_frame_row_with_spaces (to, to_used);
26632 }
26633
26634
26635
26636
26637
26638
26639
26640
26641
26642
26643
26644
26645
26646
26647
26648
26649
26650
26651
26652
26653
26654
26655 void
26656 display_tty_menu_item (const char *item_text, int width, int face_id,
26657 int x, int y, bool submenu)
26658 {
26659 struct it it;
26660 struct frame *f = SELECTED_FRAME ();
26661 struct window *w = XWINDOW (f->selected_window);
26662 struct glyph_row *row;
26663 size_t item_len = strlen (item_text);
26664
26665 eassert (FRAME_TERMCAP_P (f));
26666
26667
26668
26669
26670
26671
26672 if (y >= f->desired_matrix->nrows)
26673 return;
26674
26675 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26676 it.first_visible_x = 0;
26677 it.last_visible_x = FRAME_COLS (f) - 1;
26678 row = it.glyph_row;
26679
26680 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26681 bool saved_width = row->full_width_p;
26682 row->full_width_p = true;
26683 bool saved_reversed = row->reversed_p;
26684 row->reversed_p = false;
26685 row->enabled_p = true;
26686
26687
26688
26689 eassert (x < f->desired_matrix->matrix_w);
26690 it.current_x = it.hpos = x;
26691 it.current_y = it.vpos = y;
26692 int saved_used = row->used[TEXT_AREA];
26693 bool saved_truncated = row->truncated_on_right_p;
26694 row->used[TEXT_AREA] = x;
26695 it.face_id = face_id;
26696 it.line_wrap = TRUNCATE;
26697
26698
26699
26700
26701
26702
26703 it.paragraph_embedding = L2R;
26704
26705
26706 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26707 width--;
26708
26709 if (submenu)
26710 {
26711 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26712 item_len, 0, FRAME_COLS (f) - 1, -1);
26713 width -= item_len;
26714
26715 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26716 FRAME_COLS (f) - 1, -1);
26717 }
26718 else
26719 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26720 width, 0, FRAME_COLS (f) - 1, -1);
26721
26722 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26723 row->truncated_on_right_p = saved_truncated;
26724 row->hash = row_hash (row);
26725 row->full_width_p = saved_width;
26726 row->reversed_p = saved_reversed;
26727 }
26728
26729
26730
26731
26732
26733
26734
26735
26736
26737
26738 static int
26739 redisplay_mode_lines (Lisp_Object window, bool force)
26740 {
26741 int nwindows = 0;
26742
26743 while (!NILP (window))
26744 {
26745 struct window *w = XWINDOW (window);
26746
26747 if (WINDOWP (w->contents))
26748 nwindows += redisplay_mode_lines (w->contents, force);
26749 else if (force
26750 || FRAME_GARBAGED_P (XFRAME (w->frame))
26751 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26752 {
26753 struct text_pos lpoint;
26754 struct buffer *old = current_buffer;
26755
26756
26757 SET_TEXT_POS (lpoint, PT, PT_BYTE);
26758 set_buffer_internal_1 (XBUFFER (w->contents));
26759
26760
26761
26762 if (!EQ (window, selected_window))
26763 {
26764 struct text_pos pt;
26765
26766 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
26767 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
26768 }
26769
26770
26771 clear_glyph_matrix (w->desired_matrix);
26772 if (display_mode_lines (w))
26773 ++nwindows;
26774
26775
26776 set_buffer_internal_1 (old);
26777 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
26778 }
26779
26780 window = w->next;
26781 }
26782
26783 return nwindows;
26784 }
26785
26786
26787
26788
26789
26790
26791 static int
26792 display_mode_lines (struct window *w)
26793 {
26794 Lisp_Object old_selected_window = selected_window;
26795 Lisp_Object new_frame = w->frame;
26796 specpdl_ref count = SPECPDL_INDEX ();
26797 int n = 0;
26798
26799 record_unwind_protect (restore_selected_window, selected_window);
26800 record_unwind_protect
26801 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
26802
26803 if (window_wants_mode_line (w))
26804 {
26805 Lisp_Object window;
26806 Lisp_Object default_help
26807 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
26808
26809
26810
26811 XSETWINDOW (window, w);
26812 if (FUNCTIONP (default_help))
26813 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
26814 else if (STRINGP (default_help))
26815 wset_mode_line_help_echo (w, default_help);
26816 else
26817 wset_mode_line_help_echo (w, Qnil);
26818 }
26819
26820 selected_frame = new_frame;
26821
26822
26823 XSETWINDOW (selected_window, w);
26824 XFRAME (new_frame)->selected_window = selected_window;
26825
26826
26827 line_number_displayed = false;
26828 w->column_number_displayed = -1;
26829
26830 if (window_wants_mode_line (w))
26831 {
26832 Lisp_Object window_mode_line_format
26833 = window_parameter (w, Qmode_line_format);
26834 struct window *sel_w = XWINDOW (old_selected_window);
26835
26836
26837 display_mode_line (w,
26838 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
26839 NILP (window_mode_line_format)
26840 ? BVAR (current_buffer, mode_line_format)
26841 : window_mode_line_format);
26842 ++n;
26843 }
26844
26845 if (window_wants_tab_line (w))
26846 {
26847 Lisp_Object window_tab_line_format
26848 = window_parameter (w, Qtab_line_format);
26849
26850 display_mode_line (w, TAB_LINE_FACE_ID,
26851 NILP (window_tab_line_format)
26852 ? BVAR (current_buffer, tab_line_format)
26853 : window_tab_line_format);
26854 ++n;
26855 }
26856
26857 if (window_wants_header_line (w))
26858 {
26859 Lisp_Object window_header_line_format
26860 = window_parameter (w, Qheader_line_format);
26861
26862 display_mode_line (w, HEADER_LINE_FACE_ID,
26863 NILP (window_header_line_format)
26864 ? BVAR (current_buffer, header_line_format)
26865 : window_header_line_format);
26866 ++n;
26867 }
26868
26869 unbind_to (count, Qnil);
26870
26871 if (n > 0)
26872 w->must_be_updated_p = true;
26873 return n;
26874 }
26875
26876
26877
26878
26879
26880
26881
26882
26883 static int
26884 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
26885 {
26886 struct it it;
26887 struct face *face;
26888 specpdl_ref count = SPECPDL_INDEX ();
26889
26890 init_iterator (&it, w, -1, -1, NULL, face_id);
26891
26892
26893 it.glyph_row->enabled_p = false;
26894 prepare_desired_row (w, it.glyph_row, true);
26895
26896 it.glyph_row->mode_line_p = true;
26897 if (face_id == TAB_LINE_FACE_ID)
26898 {
26899 it.glyph_row->tab_line_p = true;
26900 w->desired_matrix->tab_line_p = true;
26901 }
26902 else if (face_id == HEADER_LINE_FACE_ID)
26903 w->desired_matrix->header_line_p = true;
26904
26905
26906
26907
26908 it.paragraph_embedding = L2R;
26909
26910 record_unwind_protect (unwind_format_mode_line,
26911 format_mode_line_unwind_data (NULL, NULL,
26912 Qnil, false));
26913
26914
26915
26916
26917 push_kboard (FRAME_KBOARD (it.f));
26918 record_unwind_save_match_data ();
26919
26920 if (NILP (Vmode_line_compact)
26921 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
26922 {
26923 mode_line_target = MODE_LINE_DISPLAY;
26924 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
26925 }
26926 else
26927 {
26928 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
26929 if (EQ (Vmode_line_compact, Qlong)
26930 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
26931 {
26932
26933
26934 display_string (NULL, mode_string, Qnil,
26935 0, 0, &it, 0, 0, 0,
26936 STRING_MULTIBYTE (mode_string));
26937 }
26938 else
26939 {
26940
26941 ptrdiff_t i = 0, i_byte = 0, start = 0;
26942 int prev = 0;
26943
26944 while (i < SCHARS (mode_string))
26945 {
26946 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
26947 if (c == ' ' && prev == ' ')
26948 {
26949 display_string (NULL,
26950 Fsubstring (mode_string, make_fixnum (start),
26951 make_fixnum (i - 1)),
26952 Qnil, 0, 0, &it, 0, 0, 0,
26953 STRING_MULTIBYTE (mode_string));
26954
26955 while (c == ' ' && i < SCHARS (mode_string))
26956 c = fetch_string_char_advance (mode_string, &i, &i_byte);
26957 start = i - 1;
26958 }
26959 prev = c;
26960 }
26961
26962
26963 if (start < i)
26964 display_string (NULL,
26965 Fsubstring (mode_string, make_fixnum (start),
26966 make_fixnum (i)),
26967 Qnil, 0, 0, &it, 0, 0, 0,
26968 STRING_MULTIBYTE (mode_string));
26969 }
26970 }
26971 pop_kboard ();
26972
26973 unbind_to (count, Qnil);
26974
26975
26976 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
26977
26978 compute_line_metrics (&it);
26979 it.glyph_row->full_width_p = true;
26980 it.glyph_row->continued_p = false;
26981 it.glyph_row->truncated_on_left_p = false;
26982 it.glyph_row->truncated_on_right_p = false;
26983
26984
26985 face = FACE_FROM_ID (it.f, face_id);
26986 extend_face_to_end_of_line (&it);
26987 if (face->box != FACE_NO_BOX)
26988 {
26989 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26990 + it.glyph_row->used[TEXT_AREA] - 1);
26991 int box_thickness = face->box_vertical_line_width;
26992 last->right_box_line_p = true;
26993
26994
26995
26996
26997
26998
26999 if (box_thickness > 0)
27000 last->pixel_width += max (0, (box_thickness
27001 - (it.current_x - it.last_visible_x)));
27002 }
27003
27004 return it.glyph_row->height;
27005 }
27006
27007
27008
27009
27010 static Lisp_Object
27011 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
27012 {
27013 register Lisp_Object tail, prev;
27014 register Lisp_Object tem;
27015
27016 tail = list;
27017 prev = Qnil;
27018 while (CONSP (tail))
27019 {
27020 tem = XCAR (tail);
27021
27022 if (EQ (elt, tem))
27023 {
27024
27025 if (NILP (prev))
27026 list = XCDR (tail);
27027 else
27028 Fsetcdr (prev, XCDR (tail));
27029
27030
27031 Fsetcdr (tail, list);
27032 return tail;
27033 }
27034 else
27035 prev = tail;
27036 tail = XCDR (tail);
27037 maybe_quit ();
27038 }
27039
27040
27041 return list;
27042 }
27043
27044
27045
27046
27047
27048 static Lisp_Object
27049 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
27050 {
27051 eassert (nargs == 4);
27052 return Fset_text_properties (args[0], args[1], args[2], args[3]);
27053 }
27054
27055
27056
27057
27058
27059
27060
27061
27062
27063
27064
27065
27066
27067
27068
27069
27070
27071
27072
27073
27074
27075
27076
27077
27078
27079 static int
27080 display_mode_element (struct it *it, int depth, int field_width, int precision,
27081 Lisp_Object elt, Lisp_Object props, bool risky)
27082 {
27083 int n = 0, field, prec;
27084 bool literal = false;
27085
27086 tail_recurse:
27087 if (depth > 100)
27088 elt = build_string ("*too-deep*");
27089
27090 depth++;
27091
27092 switch (XTYPE (elt))
27093 {
27094 case Lisp_String:
27095 {
27096
27097 unsigned char c;
27098 ptrdiff_t offset = 0;
27099
27100 if (SCHARS (elt) > 0
27101 && (!NILP (props) || risky))
27102 {
27103 Lisp_Object oprops, aelt;
27104 oprops = Ftext_properties_at (make_fixnum (0), elt);
27105
27106
27107
27108
27109
27110 if (NILP (Fequal (props, oprops)) || risky)
27111 {
27112
27113
27114 if (! NILP (oprops) && !risky)
27115 {
27116 Lisp_Object tem;
27117
27118 oprops = Fcopy_sequence (oprops);
27119 tem = props;
27120 while (CONSP (tem))
27121 {
27122 oprops = plist_put (oprops, XCAR (tem),
27123 XCAR (XCDR (tem)));
27124 tem = XCDR (XCDR (tem));
27125 }
27126 props = oprops;
27127 }
27128
27129 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27130 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27131 {
27132
27133
27134 elt = XCAR (aelt);
27135 mode_line_proptrans_alist
27136 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27137 }
27138 else
27139 {
27140 Lisp_Object tem;
27141
27142
27143
27144 if (! NILP (aelt))
27145 mode_line_proptrans_alist
27146 = Fdelq (aelt, mode_line_proptrans_alist);
27147
27148 elt = Fcopy_sequence (elt);
27149
27150
27151
27152 internal_condition_case_n (safe_set_text_properties,
27153 4,
27154 ((Lisp_Object [])
27155 {make_fixnum (0),
27156 Flength (elt),
27157 props,
27158 elt}),
27159 Qt, safe_eval_handler);
27160
27161 mode_line_proptrans_alist
27162 = Fcons (Fcons (elt, props),
27163 mode_line_proptrans_alist);
27164
27165
27166 tem = Fnthcdr (make_fixnum (50),
27167 mode_line_proptrans_alist);
27168 if (! NILP (tem))
27169 XSETCDR (tem, Qnil);
27170 }
27171 }
27172 }
27173
27174 offset = 0;
27175
27176 if (literal)
27177 {
27178 prec = precision - n;
27179 switch (mode_line_target)
27180 {
27181 case MODE_LINE_NOPROP:
27182 case MODE_LINE_TITLE:
27183 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27184 break;
27185 case MODE_LINE_STRING:
27186 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27187 break;
27188 case MODE_LINE_DISPLAY:
27189 n += display_string (NULL, elt, Qnil, 0, 0, it,
27190 0, prec, 0, STRING_MULTIBYTE (elt));
27191 break;
27192 }
27193
27194 break;
27195 }
27196
27197
27198
27199 while ((precision <= 0 || n < precision)
27200 && SREF (elt, offset) != 0
27201 && (mode_line_target != MODE_LINE_DISPLAY
27202 || it->current_x < it->last_visible_x))
27203 {
27204 ptrdiff_t last_offset = offset;
27205
27206
27207 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27208 ;
27209
27210 if (offset - 1 != last_offset)
27211 {
27212 ptrdiff_t nchars, nbytes;
27213
27214
27215
27216
27217 offset--;
27218
27219 prec = c_string_width (SDATA (elt) + last_offset,
27220 offset - last_offset, precision - n,
27221 &nchars, &nbytes);
27222
27223 switch (mode_line_target)
27224 {
27225 case MODE_LINE_NOPROP:
27226 case MODE_LINE_TITLE:
27227 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27228 break;
27229 case MODE_LINE_STRING:
27230 {
27231 ptrdiff_t bytepos = last_offset;
27232 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27233 ptrdiff_t endpos = (precision <= 0
27234 ? string_byte_to_char (elt, offset)
27235 : charpos + nchars);
27236 Lisp_Object mode_string
27237 = Fsubstring (elt, make_fixnum (charpos),
27238 make_fixnum (endpos));
27239 n += store_mode_line_string (NULL, mode_string, false,
27240 0, 0, Qnil);
27241 }
27242 break;
27243 case MODE_LINE_DISPLAY:
27244 {
27245 ptrdiff_t bytepos = last_offset;
27246 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27247
27248 if (precision <= 0)
27249 nchars = string_byte_to_char (elt, offset) - charpos;
27250 n += display_string (NULL, elt, Qnil, 0, charpos,
27251 it, 0, nchars, 0,
27252 STRING_MULTIBYTE (elt));
27253 }
27254 break;
27255 }
27256 }
27257 else
27258 {
27259 ptrdiff_t percent_position = offset;
27260
27261
27262
27263 field = 0;
27264 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27265 field = field * 10 + c - '0';
27266
27267
27268 if (field_width - n > 0 && field > field_width - n)
27269 field = field_width - n;
27270
27271
27272 prec = precision - n;
27273
27274 if (c == 'M')
27275 n += display_mode_element (it, depth, field, prec,
27276 Vglobal_mode_string, props,
27277 risky);
27278 else if (c != 0)
27279 {
27280 bool multibyte;
27281 ptrdiff_t bytepos, charpos;
27282 const char *spec;
27283 Lisp_Object string;
27284
27285 bytepos = percent_position;
27286 charpos = (STRING_MULTIBYTE (elt)
27287 ? string_byte_to_char (elt, bytepos)
27288 : bytepos);
27289 spec = decode_mode_spec (it->w, c, field, &string);
27290 eassert (NILP (string) || STRINGP (string));
27291 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27292
27293
27294 ptrdiff_t nbytes = strlen (spec);
27295 ptrdiff_t nchars, mb_nbytes;
27296 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27297 &nchars, &mb_nbytes);
27298 if (!(nbytes == nchars || nbytes != mb_nbytes))
27299 multibyte = true;
27300
27301 switch (mode_line_target)
27302 {
27303 case MODE_LINE_NOPROP:
27304 case MODE_LINE_TITLE:
27305 n += store_mode_line_noprop (spec, field, prec);
27306 break;
27307 case MODE_LINE_STRING:
27308 {
27309 Lisp_Object tem = build_string (spec);
27310 props = Ftext_properties_at (make_fixnum (charpos), elt);
27311
27312 n += store_mode_line_string (NULL, tem, false,
27313 field, prec, props);
27314 }
27315 break;
27316 case MODE_LINE_DISPLAY:
27317 {
27318 int nglyphs_before, nwritten;
27319
27320 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27321 nwritten = display_string (spec, string, elt,
27322 charpos, 0, it,
27323 field, prec, 0,
27324 multibyte);
27325
27326
27327
27328
27329 if (nwritten > 0)
27330 {
27331 struct glyph *glyph
27332 = (it->glyph_row->glyphs[TEXT_AREA]
27333 + nglyphs_before);
27334 int i;
27335
27336 for (i = 0; i < nwritten; ++i)
27337 {
27338 glyph[i].object = elt;
27339 glyph[i].charpos = charpos;
27340 }
27341
27342 n += nwritten;
27343 }
27344 }
27345 break;
27346 }
27347 }
27348 else
27349 break;
27350 }
27351 }
27352 }
27353 break;
27354
27355 case Lisp_Symbol:
27356
27357
27358
27359
27360 {
27361 register Lisp_Object tem;
27362
27363
27364
27365 if (NILP (Fget (elt, Qrisky_local_variable)))
27366 risky = true;
27367
27368 tem = Fboundp (elt);
27369 if (!NILP (tem))
27370 {
27371 tem = Fsymbol_value (elt);
27372
27373
27374 if (STRINGP (tem))
27375 literal = true;
27376
27377 if (!EQ (tem, elt))
27378 {
27379
27380 elt = tem;
27381 goto tail_recurse;
27382 }
27383 }
27384 }
27385 break;
27386
27387 case Lisp_Cons:
27388 {
27389 register Lisp_Object car, tem;
27390
27391
27392
27393
27394
27395
27396
27397
27398
27399
27400 car = XCAR (elt);
27401 if (EQ (car, QCeval))
27402 {
27403
27404
27405
27406 if (risky)
27407 break;
27408
27409 if (CONSP (XCDR (elt)))
27410 {
27411 Lisp_Object spec;
27412 spec = safe__eval (true, XCAR (XCDR (elt)));
27413
27414
27415
27416
27417
27418
27419 if (!FRAME_LIVE_P (it->f))
27420 signal_error (":eval deleted the frame being displayed", elt);
27421 n += display_mode_element (it, depth, field_width - n,
27422 precision - n, spec, props,
27423 risky);
27424 }
27425 }
27426 else if (EQ (car, QCpropertize))
27427 {
27428
27429
27430
27431 if (risky)
27432 break;
27433
27434 if (CONSP (XCDR (elt)))
27435 n += display_mode_element (it, depth, field_width - n,
27436 precision - n, XCAR (XCDR (elt)),
27437 XCDR (XCDR (elt)), risky);
27438 }
27439 else if (SYMBOLP (car))
27440 {
27441 tem = Fboundp (car);
27442 elt = XCDR (elt);
27443 if (!CONSP (elt))
27444 goto invalid;
27445
27446
27447 if (!NILP (tem))
27448 {
27449 tem = Fsymbol_value (car);
27450 if (!NILP (tem))
27451 {
27452 elt = XCAR (elt);
27453 goto tail_recurse;
27454 }
27455 }
27456
27457
27458
27459 elt = XCDR (elt);
27460 if (NILP (elt))
27461 break;
27462 else if (!CONSP (elt))
27463 goto invalid;
27464 elt = XCAR (elt);
27465 goto tail_recurse;
27466 }
27467 else if (FIXNUMP (car))
27468 {
27469 register int lim = XFIXNUM (car);
27470 elt = XCDR (elt);
27471 if (lim < 0)
27472 {
27473
27474 if (precision <= 0)
27475 precision = -lim;
27476 else
27477 precision = min (precision, -lim);
27478 }
27479 else if (lim > 0)
27480 {
27481
27482
27483 if (precision > 0)
27484 lim = min (precision, lim);
27485
27486
27487
27488
27489 field_width = max (lim, field_width);
27490 }
27491 goto tail_recurse;
27492 }
27493 else if (STRINGP (car) || CONSP (car))
27494 FOR_EACH_TAIL_SAFE (elt)
27495 {
27496 if (0 < precision && precision <= n)
27497 break;
27498 n += display_mode_element (it, depth,
27499
27500
27501 (! CONSP (XCDR (elt))
27502 ? field_width - n
27503 : 0),
27504 precision - n, XCAR (elt),
27505 props, risky);
27506 }
27507 }
27508 break;
27509
27510 default:
27511 invalid:
27512 elt = build_string ("*invalid*");
27513 goto tail_recurse;
27514 }
27515
27516
27517 if (field_width > 0 && n < field_width)
27518 {
27519 switch (mode_line_target)
27520 {
27521 case MODE_LINE_NOPROP:
27522 case MODE_LINE_TITLE:
27523 n += store_mode_line_noprop ("", field_width - n, 0);
27524 break;
27525 case MODE_LINE_STRING:
27526 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27527 Qnil);
27528 break;
27529 case MODE_LINE_DISPLAY:
27530 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27531 0, 0, 0);
27532 break;
27533 }
27534 }
27535
27536 return n;
27537 }
27538
27539
27540
27541
27542
27543
27544
27545
27546
27547
27548
27549
27550
27551
27552
27553
27554
27555
27556
27557
27558 static int
27559 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27560 bool copy_string,
27561 int field_width, int precision, Lisp_Object props)
27562 {
27563 ptrdiff_t len;
27564 int n = 0;
27565
27566 if (string != NULL)
27567 {
27568 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27569 lisp_string = make_string (string, len);
27570 if (NILP (props))
27571 props = mode_line_string_face_prop;
27572 else if (!NILP (mode_line_string_face))
27573 {
27574 Lisp_Object face = plist_get (props, Qface);
27575 props = Fcopy_sequence (props);
27576 if (NILP (face))
27577 face = mode_line_string_face;
27578 else
27579 face = list2 (face, mode_line_string_face);
27580 props = plist_put (props, Qface, face);
27581 }
27582 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27583 props, lisp_string);
27584 }
27585 else
27586 {
27587 len = SCHARS (lisp_string);
27588 if (precision > 0 && len > precision)
27589 {
27590 len = precision;
27591 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27592 precision = -1;
27593 }
27594 if (!NILP (mode_line_string_face))
27595 {
27596 Lisp_Object face;
27597 if (NILP (props))
27598 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27599 face = plist_get (props, Qface);
27600 if (NILP (face))
27601 face = mode_line_string_face;
27602 else
27603 face = list2 (face, mode_line_string_face);
27604 props = list2 (Qface, face);
27605 if (copy_string)
27606 lisp_string = Fcopy_sequence (lisp_string);
27607 }
27608 if (!NILP (props))
27609 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27610 props, lisp_string);
27611 }
27612
27613 if (len > 0)
27614 {
27615 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27616 n += len;
27617 }
27618
27619 if (field_width > len)
27620 {
27621 field_width -= len;
27622 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27623 Qnil);
27624 if (!NILP (props))
27625 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27626 props, lisp_string);
27627 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27628 n += field_width;
27629 }
27630
27631 return n;
27632 }
27633
27634
27635 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27636 1, 4, 0,
27637 doc:
27638
27639
27640
27641
27642
27643
27644
27645
27646
27647
27648
27649
27650
27651
27652
27653 )
27654 (Lisp_Object format, Lisp_Object face,
27655 Lisp_Object window, Lisp_Object buffer)
27656 {
27657 struct it it;
27658 int len;
27659 struct window *w;
27660 struct buffer *old_buffer = NULL;
27661 int face_id;
27662 bool no_props = FIXNUMP (face);
27663 specpdl_ref count = SPECPDL_INDEX ();
27664 Lisp_Object str;
27665 int string_start = 0;
27666
27667 w = decode_any_window (window);
27668 XSETWINDOW (window, w);
27669
27670 if (NILP (buffer))
27671 buffer = w->contents;
27672 CHECK_BUFFER (buffer);
27673
27674
27675
27676 if (NILP (format) || noninteractive)
27677 return empty_unibyte_string;
27678
27679 if (no_props)
27680 face = Qnil;
27681
27682 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27683 : EQ (face, Qt) ? (EQ (window, selected_window)
27684 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27685 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27686 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27687 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27688 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27689 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27690 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27691 : DEFAULT_FACE_ID;
27692
27693 old_buffer = current_buffer;
27694
27695
27696
27697 record_unwind_protect (unwind_format_mode_line,
27698 format_mode_line_unwind_data
27699 (XFRAME (WINDOW_FRAME (w)),
27700 old_buffer, selected_window, true));
27701 mode_line_proptrans_alist = Qnil;
27702
27703 Fselect_window (window, Qt);
27704 set_buffer_internal_1 (XBUFFER (buffer));
27705
27706 init_iterator (&it, w, -1, -1, NULL, face_id);
27707
27708 if (no_props)
27709 {
27710 mode_line_target = MODE_LINE_NOPROP;
27711 mode_line_string_face_prop = Qnil;
27712 mode_line_string_list = Qnil;
27713 string_start = MODE_LINE_NOPROP_LEN (0);
27714 }
27715 else
27716 {
27717 mode_line_target = MODE_LINE_STRING;
27718 mode_line_string_list = Qnil;
27719 mode_line_string_face = face;
27720 mode_line_string_face_prop
27721 = NILP (face) ? Qnil : list2 (Qface, face);
27722 }
27723
27724 push_kboard (FRAME_KBOARD (it.f));
27725 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27726 pop_kboard ();
27727
27728 if (no_props)
27729 {
27730 len = MODE_LINE_NOPROP_LEN (string_start);
27731 str = make_string (mode_line_noprop_buf + string_start, len);
27732 }
27733 else
27734 {
27735 mode_line_string_list = Fnreverse (mode_line_string_list);
27736 str = Fmapconcat (Qidentity, mode_line_string_list,
27737 empty_unibyte_string);
27738 }
27739
27740 return unbind_to (count, str);
27741 }
27742
27743
27744
27745
27746 static void
27747 pint2str (register char *buf, register int width, register ptrdiff_t d)
27748 {
27749 register char *p = buf;
27750
27751 if (d <= 0)
27752 *p++ = '0';
27753 else
27754 {
27755 while (d > 0)
27756 {
27757 *p++ = d % 10 + '0';
27758 d /= 10;
27759 }
27760 }
27761
27762 for (width -= (int) (p - buf); width > 0; --width)
27763 *p++ = ' ';
27764 *p-- = '\0';
27765 while (p > buf)
27766 {
27767 d = *buf;
27768 *buf++ = *p;
27769 *p-- = d;
27770 }
27771 }
27772
27773
27774
27775
27776
27777 static const char power_letter[] =
27778 {
27779 0,
27780 'k',
27781 'M',
27782 'G',
27783 'T',
27784 'P',
27785 'E',
27786 'Z',
27787 'Y',
27788 'R',
27789 'Q'
27790 };
27791
27792 static void
27793 pint2hrstr (char *buf, int width, ptrdiff_t d)
27794 {
27795
27796
27797 ptrdiff_t quotient = d;
27798 int remainder = 0;
27799
27800 int tenths = -1;
27801 int exponent = 0;
27802
27803
27804 int length;
27805
27806 char * psuffix;
27807 char * p;
27808
27809 if (quotient >= 1000)
27810 {
27811
27812 do
27813 {
27814 remainder = quotient % 1000;
27815 quotient /= 1000;
27816 exponent++;
27817 }
27818 while (quotient >= 1000);
27819
27820
27821 if (quotient <= 9)
27822 {
27823 tenths = remainder / 100;
27824 if (remainder % 100 >= 50)
27825 {
27826 if (tenths < 9)
27827 tenths++;
27828 else
27829 {
27830 quotient++;
27831 if (quotient == 10)
27832 tenths = -1;
27833 else
27834 tenths = 0;
27835 }
27836 }
27837 }
27838 else
27839 if (remainder >= 500)
27840 {
27841 if (quotient < 999)
27842 quotient++;
27843 else
27844 {
27845 quotient = 1;
27846 exponent++;
27847 tenths = 0;
27848 }
27849 }
27850 }
27851
27852
27853 if (tenths == -1 && quotient <= 99)
27854 if (quotient <= 9)
27855 length = 1;
27856 else
27857 length = 2;
27858 else
27859 length = 3;
27860 p = psuffix = buf + max (width, length);
27861
27862
27863 *psuffix++ = power_letter[exponent];
27864 *psuffix = '\0';
27865
27866
27867 if (tenths >= 0)
27868 {
27869 *--p = '0' + tenths;
27870 *--p = '.';
27871 }
27872
27873
27874 do
27875 {
27876 int digit = quotient % 10;
27877 *--p = '0' + digit;
27878 }
27879 while ((quotient /= 10) != 0);
27880
27881
27882 while (buf < p)
27883 *--p = ' ';
27884 }
27885
27886
27887
27888
27889
27890 static unsigned char invalid_eol_type[] = "(*invalid*)";
27891
27892 static char *
27893 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
27894 {
27895 Lisp_Object val;
27896 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
27897 const unsigned char *eol_str;
27898 int eol_str_len;
27899
27900 Lisp_Object eoltype;
27901
27902 val = CODING_SYSTEM_SPEC (coding_system);
27903 eoltype = Qnil;
27904
27905 if (!VECTORP (val))
27906 {
27907 *buf++ = multibyte ? '-' : ' ';
27908 if (eol_flag)
27909 eoltype = eol_mnemonic_undecided;
27910
27911 }
27912 else
27913 {
27914 Lisp_Object attrs;
27915 Lisp_Object eolvalue;
27916
27917 attrs = AREF (val, 0);
27918 eolvalue = AREF (val, 2);
27919
27920 if (multibyte)
27921 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
27922 (unsigned char *) buf);
27923 else
27924 *buf++ = ' ';
27925
27926 if (eol_flag)
27927 {
27928
27929
27930 if (NILP (eolvalue))
27931 eoltype = eol_mnemonic_undecided;
27932 else if (VECTORP (eolvalue))
27933 eoltype = eol_mnemonic_undecided;
27934 else
27935 eoltype = (EQ (eolvalue, Qunix)
27936 ? eol_mnemonic_unix
27937 : EQ (eolvalue, Qdos)
27938 ? eol_mnemonic_dos : eol_mnemonic_mac);
27939 }
27940 }
27941
27942 if (eol_flag)
27943 {
27944
27945 if (STRINGP (eoltype))
27946 {
27947 eol_str = SDATA (eoltype);
27948 eol_str_len = SBYTES (eoltype);
27949 }
27950 else if (CHARACTERP (eoltype))
27951 {
27952 int c = XFIXNAT (eoltype);
27953 return buf + CHAR_STRING (c, (unsigned char *) buf);
27954 }
27955 else
27956 {
27957 eol_str = invalid_eol_type;
27958 eol_str_len = sizeof (invalid_eol_type) - 1;
27959 }
27960 memcpy (buf, eol_str, eol_str_len);
27961 buf += eol_str_len;
27962 }
27963
27964 return buf;
27965 }
27966
27967
27968
27969
27970 static int
27971 percent99 (ptrdiff_t n, ptrdiff_t d)
27972 {
27973 int percent = (d - 1 + 100.0 * n) / d;
27974 return min (percent, 99);
27975 }
27976
27977
27978
27979
27980
27981
27982
27983
27984
27985 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
27986
27987 static const char *
27988 decode_mode_spec (struct window *w, register int c, int field_width,
27989 Lisp_Object *string)
27990 {
27991 Lisp_Object obj;
27992 struct frame *f = XFRAME (WINDOW_FRAME (w));
27993 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
27994
27995
27996
27997
27998
27999 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
28000 struct buffer *b = current_buffer;
28001
28002 obj = Qnil;
28003 *string = Qnil;
28004
28005 switch (c)
28006 {
28007 case '*':
28008 if (!NILP (BVAR (b, read_only)))
28009 return "%";
28010 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28011 return "*";
28012 return "-";
28013
28014 case '+':
28015
28016 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28017 return "*";
28018 if (!NILP (BVAR (b, read_only)))
28019 return "%";
28020 return "-";
28021
28022 case '&':
28023
28024 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28025 return "*";
28026 return "-";
28027
28028 case '%':
28029 return "%";
28030
28031 case '[':
28032 {
28033 int i;
28034 char *p;
28035
28036 if (command_loop_level > 5)
28037 return "[[[... ";
28038 p = decode_mode_spec_buf;
28039 for (i = 0; i < command_loop_level; i++)
28040 *p++ = '[';
28041 *p = 0;
28042 return decode_mode_spec_buf;
28043 }
28044
28045 case ']':
28046 {
28047 int i;
28048 char *p;
28049
28050 if (command_loop_level > 5)
28051 return " ...]]]";
28052 p = decode_mode_spec_buf;
28053 for (i = 0; i < command_loop_level; i++)
28054 *p++ = ']';
28055 *p = 0;
28056 return decode_mode_spec_buf;
28057 }
28058
28059 case '-':
28060 {
28061 register int i;
28062
28063
28064 if (mode_line_target == MODE_LINE_NOPROP
28065 || mode_line_target == MODE_LINE_STRING)
28066 return "--";
28067 if (field_width <= 0
28068 || field_width > sizeof (lots_of_dashes))
28069 {
28070 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28071 decode_mode_spec_buf[i] = '-';
28072 decode_mode_spec_buf[i] = '\0';
28073 return decode_mode_spec_buf;
28074 }
28075 else
28076 return lots_of_dashes;
28077 }
28078
28079 case 'b':
28080 obj = BVAR (b, name);
28081 break;
28082
28083 case 'c':
28084 case 'C':
28085
28086
28087
28088
28089
28090 if (mode_line_target == MODE_LINE_TITLE)
28091 return "";
28092 else
28093 {
28094 ptrdiff_t col = current_column ();
28095 int disp_col = (c == 'C') ? col + 1 : col;
28096 w->column_number_displayed = col;
28097 pint2str (decode_mode_spec_buf, width, disp_col);
28098 return decode_mode_spec_buf;
28099 }
28100
28101 case 'e':
28102 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28103 {
28104 if (NILP (Vmemory_full))
28105 return "";
28106 else
28107 return "!MEM FULL! ";
28108 }
28109 #else
28110 return "";
28111 #endif
28112
28113 case 'F':
28114
28115 if (!NILP (f->title))
28116 return SSDATA (f->title);
28117 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28118 return SSDATA (f->name);
28119 return "Emacs";
28120
28121 case 'f':
28122 obj = BVAR (b, filename);
28123 break;
28124
28125 case 'i':
28126 {
28127 ptrdiff_t size = ZV - BEGV;
28128 pint2str (decode_mode_spec_buf, width, size);
28129 return decode_mode_spec_buf;
28130 }
28131
28132 case 'I':
28133 {
28134 ptrdiff_t size = ZV - BEGV;
28135 pint2hrstr (decode_mode_spec_buf, width, size);
28136 return decode_mode_spec_buf;
28137 }
28138
28139 case 'l':
28140 {
28141 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28142 ptrdiff_t topline, nlines, height;
28143 ptrdiff_t junk;
28144
28145
28146 if (mode_line_target == MODE_LINE_TITLE)
28147 return "";
28148
28149 startpos = marker_position (w->start);
28150 startpos_byte = marker_byte_position (w->start);
28151 height = WINDOW_TOTAL_LINES (w);
28152
28153
28154
28155
28156
28157
28158
28159
28160 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28161 && startpos_byte <= BUF_ZV_BYTE (b)))
28162 {
28163 startpos = BUF_BEGV (b);
28164 startpos_byte = BUF_BEGV_BYTE (b);
28165 w->base_line_pos = 0;
28166 w->base_line_number = 0;
28167 }
28168
28169
28170
28171 if (w->base_line_pos == -1)
28172 goto no_value;
28173
28174
28175 if (FIXNUMP (Vline_number_display_limit)
28176 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28177 {
28178 w->base_line_pos = 0;
28179 w->base_line_number = 0;
28180 goto no_value;
28181 }
28182
28183 if (w->base_line_number > 0
28184 && w->base_line_pos > 0
28185 && w->base_line_pos <= startpos)
28186 {
28187 line = w->base_line_number;
28188 linepos = w->base_line_pos;
28189 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28190 }
28191 else
28192 {
28193 line = 1;
28194 linepos = BUF_BEGV (b);
28195 linepos_byte = BUF_BEGV_BYTE (b);
28196 }
28197
28198
28199 nlines = display_count_lines (linepos_byte,
28200 startpos_byte,
28201 startpos, &junk);
28202
28203 topline = nlines + line;
28204
28205
28206
28207
28208
28209 if (startpos == BUF_BEGV (b))
28210 {
28211 w->base_line_number = topline;
28212 w->base_line_pos = BUF_BEGV (b);
28213 }
28214 else if (nlines < height + 25 || nlines > height * 3 + 50
28215 || linepos == BUF_BEGV (b))
28216 {
28217 ptrdiff_t limit = BUF_BEGV (b);
28218 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28219 ptrdiff_t position;
28220 ptrdiff_t distance
28221 = (line_number_display_limit_width < 0 ? 0
28222 : ckd_mul (&distance, line_number_display_limit_width,
28223 height * 2 + 30)
28224 ? PTRDIFF_MAX : distance);
28225
28226 if (startpos - distance > limit)
28227 {
28228 limit = startpos - distance;
28229 limit_byte = CHAR_TO_BYTE (limit);
28230 }
28231
28232 nlines = display_count_lines (startpos_byte,
28233 limit_byte,
28234 - (height * 2 + 30),
28235 &position);
28236
28237
28238
28239 if (position == limit_byte && limit == startpos - distance)
28240 {
28241 w->base_line_pos = -1;
28242 w->base_line_number = 0;
28243 goto no_value;
28244 }
28245
28246 w->base_line_number = topline - nlines;
28247 w->base_line_pos = BYTE_TO_CHAR (position);
28248 }
28249
28250
28251 nlines = display_count_lines (startpos_byte,
28252 PT_BYTE, PT, &junk);
28253
28254
28255 line_number_displayed = true;
28256
28257
28258 pint2str (decode_mode_spec_buf, width, topline + nlines);
28259 return decode_mode_spec_buf;
28260 no_value:
28261 {
28262 char *p = decode_mode_spec_buf;
28263 int pad = width - 2;
28264 while (pad-- > 0)
28265 *p++ = ' ';
28266 *p++ = '?';
28267 *p++ = '?';
28268 *p = '\0';
28269 return decode_mode_spec_buf;
28270 }
28271 }
28272 break;
28273
28274 case 'm':
28275 obj = BVAR (b, mode_name);
28276 break;
28277
28278 case 'n':
28279 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28280 return " Narrow";
28281 break;
28282
28283
28284 case 'o':
28285 {
28286 ptrdiff_t toppos = marker_position (w->start);
28287 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28288 ptrdiff_t begv = BUF_BEGV (b);
28289 ptrdiff_t zv = BUF_ZV (b);
28290
28291 if (zv <= botpos)
28292 return toppos <= begv ? "All" : "Bottom";
28293 else if (toppos <= begv)
28294 return "Top";
28295 else
28296 {
28297 sprintf (decode_mode_spec_buf, "%2d%%",
28298 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28299 return decode_mode_spec_buf;
28300 }
28301 }
28302
28303
28304 case 'p':
28305 {
28306 ptrdiff_t pos = marker_position (w->start);
28307 ptrdiff_t begv = BUF_BEGV (b);
28308 ptrdiff_t zv = BUF_ZV (b);
28309
28310 if (w->window_end_pos <= BUF_Z (b) - zv)
28311 return pos <= begv ? "All" : "Bottom";
28312 else if (pos <= begv)
28313 return "Top";
28314 else
28315 {
28316 sprintf (decode_mode_spec_buf, "%2d%%",
28317 percent99 (pos - begv, zv - begv));
28318 return decode_mode_spec_buf;
28319 }
28320 }
28321
28322
28323 case 'P':
28324 {
28325 ptrdiff_t toppos = marker_position (w->start);
28326 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28327 ptrdiff_t begv = BUF_BEGV (b);
28328 ptrdiff_t zv = BUF_ZV (b);
28329
28330 if (zv <= botpos)
28331 return toppos <= begv ? "All" : "Bottom";
28332 else
28333 {
28334 sprintf (decode_mode_spec_buf,
28335 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28336 percent99 (botpos - begv, zv - begv));
28337 return decode_mode_spec_buf;
28338 }
28339 }
28340
28341
28342
28343 case 'q':
28344 {
28345 ptrdiff_t toppos = marker_position (w->start);
28346 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28347 ptrdiff_t begv = BUF_BEGV (b);
28348 ptrdiff_t zv = BUF_ZV (b);
28349 int top_perc, bot_perc;
28350
28351 if ((toppos <= begv) && (zv <= botpos))
28352 return "All ";
28353
28354 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28355 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28356
28357 if (top_perc == bot_perc)
28358 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28359 else
28360 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28361
28362 return decode_mode_spec_buf;
28363 }
28364
28365 case 's':
28366
28367 obj = Fget_buffer_process (Fcurrent_buffer ());
28368 if (NILP (obj))
28369 return "no process";
28370 #ifndef MSDOS
28371 obj = Fsymbol_name (Fprocess_status (obj));
28372 #endif
28373 break;
28374
28375 case '@':
28376 {
28377 specpdl_ref count = inhibit_garbage_collection ();
28378 Lisp_Object curdir = BVAR (current_buffer, directory);
28379 Lisp_Object val = Qnil;
28380
28381 if (STRINGP (curdir))
28382 val = safe_call1 (intern ("file-remote-p"), curdir);
28383
28384 val = unbind_to (count, val);
28385
28386 if (NILP (val))
28387 return "-";
28388 else
28389 return "@";
28390 }
28391
28392 case 'z':
28393
28394 case 'Z':
28395
28396 {
28397 bool eol_flag = (c == 'Z');
28398 char *p = decode_mode_spec_buf;
28399
28400 if (! FRAME_WINDOW_P (f))
28401 {
28402
28403
28404 p = decode_mode_spec_coding (CODING_ID_NAME
28405 (FRAME_KEYBOARD_CODING (f)->id),
28406 p, false);
28407 p = decode_mode_spec_coding (CODING_ID_NAME
28408 (FRAME_TERMINAL_CODING (f)->id),
28409 p, false);
28410 }
28411 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28412 p, eol_flag);
28413
28414 #if false
28415 #ifdef subprocesses
28416 obj = Fget_buffer_process (Fcurrent_buffer ());
28417 if (PROCESSP (obj))
28418 {
28419 p = decode_mode_spec_coding
28420 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28421 p = decode_mode_spec_coding
28422 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28423 }
28424 #endif
28425 #endif
28426 *p = 0;
28427 return decode_mode_spec_buf;
28428 }
28429 }
28430
28431 if (STRINGP (obj))
28432 {
28433 *string = obj;
28434 return SSDATA (obj);
28435 }
28436 else
28437 return "";
28438 }
28439
28440
28441
28442
28443 ptrdiff_t
28444 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28445 {
28446 ptrdiff_t ignored;
28447 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28448 }
28449
28450
28451
28452
28453
28454
28455
28456
28457
28458
28459
28460 static ptrdiff_t
28461 display_count_lines (ptrdiff_t start_byte,
28462 ptrdiff_t limit_byte, ptrdiff_t count,
28463 ptrdiff_t *byte_pos_ptr)
28464 {
28465 register unsigned char *cursor;
28466 unsigned char *base;
28467
28468 register ptrdiff_t ceiling;
28469 register unsigned char *ceiling_addr;
28470 ptrdiff_t orig_count = count;
28471
28472
28473
28474 bool selective_display
28475 = (!NILP (BVAR (current_buffer, selective_display))
28476 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28477
28478 if (count > 0)
28479 {
28480 while (start_byte < limit_byte)
28481 {
28482 ceiling = BUFFER_CEILING_OF (start_byte);
28483 ceiling = min (limit_byte - 1, ceiling);
28484 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28485 base = (cursor = BYTE_POS_ADDR (start_byte));
28486
28487 do
28488 {
28489 if (selective_display)
28490 {
28491 while (*cursor != '\n' && *cursor != 015
28492 && ++cursor != ceiling_addr)
28493 continue;
28494 if (cursor == ceiling_addr)
28495 break;
28496 }
28497 else
28498 {
28499 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28500 if (! cursor)
28501 break;
28502 }
28503
28504 cursor++;
28505
28506 if (--count == 0)
28507 {
28508 start_byte += cursor - base;
28509 *byte_pos_ptr = start_byte;
28510 return orig_count;
28511 }
28512 }
28513 while (cursor < ceiling_addr);
28514
28515 start_byte += ceiling_addr - base;
28516 }
28517 }
28518 else
28519 {
28520 while (start_byte > limit_byte)
28521 {
28522 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28523 ceiling = max (limit_byte, ceiling);
28524 ceiling_addr = BYTE_POS_ADDR (ceiling);
28525 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28526 while (true)
28527 {
28528 if (selective_display)
28529 {
28530 while (--cursor >= ceiling_addr
28531 && *cursor != '\n' && *cursor != 015)
28532 continue;
28533 if (cursor < ceiling_addr)
28534 break;
28535 }
28536 else
28537 {
28538 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28539 if (! cursor)
28540 break;
28541 }
28542
28543 if (++count == 0)
28544 {
28545 start_byte += cursor - base + 1;
28546 *byte_pos_ptr = start_byte;
28547
28548
28549 return - orig_count - 1;
28550 }
28551 }
28552 start_byte += ceiling_addr - base;
28553 }
28554 }
28555
28556 *byte_pos_ptr = limit_byte;
28557
28558 if (count < 0)
28559 return - orig_count + count;
28560 return orig_count - count;
28561
28562 }
28563
28564
28565
28566
28567
28568
28569
28570
28571
28572
28573
28574
28575
28576
28577
28578
28579
28580
28581
28582
28583
28584
28585
28586
28587
28588
28589
28590
28591
28592
28593
28594
28595
28596
28597
28598
28599
28600
28601
28602
28603
28604
28605
28606
28607
28608 static int
28609 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28610 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28611 int field_width, int precision, int max_x, int multibyte)
28612 {
28613 int hpos_at_start = it->hpos;
28614 int saved_face_id = it->face_id;
28615 struct glyph_row *row = it->glyph_row;
28616 ptrdiff_t it_charpos;
28617
28618
28619
28620 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28621 start, precision, field_width, multibyte);
28622
28623 if (string && STRINGP (lisp_string))
28624
28625
28626 it->stop_charpos = it->end_charpos;
28627
28628
28629
28630 if (STRINGP (face_string))
28631 {
28632 ptrdiff_t endptr;
28633 struct face *face;
28634
28635 it->face_id
28636 = face_at_string_position (it->w, face_string, face_string_pos,
28637 0, &endptr, it->base_face_id, false, 0);
28638 face = FACE_FROM_ID (it->f, it->face_id);
28639 it->face_box_p = face->box != FACE_NO_BOX;
28640
28641
28642
28643
28644 if (NILP (lisp_string))
28645 {
28646 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28647 face_string);
28648 if (!NILP (display))
28649 {
28650 Lisp_Object min_width = plist_get (display, Qmin_width);
28651 if (!NILP (min_width))
28652 display_min_width (it, 0, face_string, min_width);
28653 }
28654 }
28655 }
28656
28657
28658
28659 if (max_x <= 0)
28660 max_x = it->last_visible_x;
28661 else
28662 max_x = min (max_x, it->last_visible_x);
28663
28664
28665
28666 if (it->current_x < it->first_visible_x)
28667 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28668 MOVE_TO_POS | MOVE_TO_X);
28669
28670 row->ascent = it->max_ascent;
28671 row->height = it->max_ascent + it->max_descent;
28672 row->phys_ascent = it->max_phys_ascent;
28673 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28674 row->extra_line_spacing = it->max_extra_line_spacing;
28675
28676 if (STRINGP (it->string))
28677 it_charpos = IT_STRING_CHARPOS (*it);
28678 else
28679 it_charpos = IT_CHARPOS (*it);
28680
28681
28682
28683 while (it->current_x < max_x)
28684 {
28685 int x_before, x, n_glyphs_before, i, nglyphs;
28686
28687
28688 if (!get_next_display_element (it))
28689 break;
28690
28691
28692 x_before = it->current_x;
28693 n_glyphs_before = row->used[TEXT_AREA];
28694 PRODUCE_GLYPHS (it);
28695
28696 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28697 i = 0;
28698 x = x_before;
28699 while (i < nglyphs)
28700 {
28701 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28702
28703 if (it->line_wrap != TRUNCATE
28704 && x + glyph->pixel_width > max_x)
28705 {
28706
28707 if (CHAR_GLYPH_PADDING_P (*glyph))
28708 {
28709
28710 if (row->reversed_p)
28711 unproduce_glyphs (it, row->used[TEXT_AREA]
28712 - n_glyphs_before);
28713 row->used[TEXT_AREA] = n_glyphs_before;
28714 it->current_x = x_before;
28715 }
28716 else
28717 {
28718 if (row->reversed_p)
28719 unproduce_glyphs (it, row->used[TEXT_AREA]
28720 - (n_glyphs_before + i));
28721 row->used[TEXT_AREA] = n_glyphs_before + i;
28722 it->current_x = x;
28723 }
28724 break;
28725 }
28726 else if (x + glyph->pixel_width >= it->first_visible_x)
28727 {
28728
28729 ++it->hpos;
28730 if (x < it->first_visible_x)
28731 row->x = x - it->first_visible_x;
28732 }
28733 else
28734 {
28735
28736
28737 emacs_abort ();
28738 }
28739
28740 row->ascent = max (row->ascent, it->max_ascent);
28741 row->height = max (row->height, it->max_ascent + it->max_descent);
28742 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28743 row->phys_height = max (row->phys_height,
28744 it->max_phys_ascent + it->max_phys_descent);
28745 row->extra_line_spacing = max (row->extra_line_spacing,
28746 it->max_extra_line_spacing);
28747 x += glyph->pixel_width;
28748 ++i;
28749 }
28750
28751
28752 if (i < nglyphs)
28753 break;
28754
28755
28756 if (ITERATOR_AT_END_OF_LINE_P (it))
28757 {
28758 it->continuation_lines_width = 0;
28759 break;
28760 }
28761
28762 set_iterator_to_next (it, true);
28763 if (STRINGP (it->string))
28764 it_charpos = IT_STRING_CHARPOS (*it);
28765 else
28766 it_charpos = IT_CHARPOS (*it);
28767
28768
28769 if (it->line_wrap == TRUNCATE
28770 && it->current_x >= it->last_visible_x)
28771 {
28772
28773
28774
28775
28776
28777
28778 if (it_charpos <= it->string_nchars)
28779 {
28780 if (!FRAME_WINDOW_P (it->f))
28781 {
28782 int ii, n;
28783
28784 if (it->current_x > it->last_visible_x)
28785 {
28786
28787
28788 bool mode_line_p = false;
28789
28790
28791
28792 if (row->mode_line_p)
28793 {
28794 struct window *w = it->w;
28795 if (row == MATRIX_MODE_LINE_ROW (w->desired_matrix))
28796 mode_line_p = true;
28797 }
28798 if (!row->reversed_p)
28799 {
28800 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
28801 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28802 break;
28803 }
28804 else
28805 {
28806 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
28807 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28808 break;
28809 unproduce_glyphs (it, ii + 1);
28810 ii = row->used[TEXT_AREA] - (ii + 1);
28811 }
28812 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
28813 {
28814 row->used[TEXT_AREA] = ii;
28815 if (row->mode_line_p)
28816 pad_mode_line (it, mode_line_p);
28817 else
28818 produce_special_glyphs (it, IT_TRUNCATION);
28819 }
28820 }
28821 produce_special_glyphs (it, IT_TRUNCATION);
28822 }
28823 row->truncated_on_right_p = true;
28824 }
28825 break;
28826 }
28827 }
28828
28829
28830 if (it->first_visible_x
28831 && it_charpos > 0)
28832 {
28833 if (!FRAME_WINDOW_P (it->f)
28834 || (row->reversed_p
28835 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
28836 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
28837 insert_left_trunc_glyphs (it);
28838 row->truncated_on_left_p = true;
28839 }
28840
28841 it->face_id = saved_face_id;
28842
28843
28844 return it->hpos - hpos_at_start;
28845 }
28846
28847
28848
28849
28850
28851
28852
28853
28854
28855
28856
28857 int
28858 invisible_prop (Lisp_Object propval, Lisp_Object list)
28859 {
28860 Lisp_Object tail, proptail;
28861
28862 for (tail = list; CONSP (tail); tail = XCDR (tail))
28863 {
28864 register Lisp_Object tem;
28865 tem = XCAR (tail);
28866 if (EQ (propval, tem))
28867 return 1;
28868 if (CONSP (tem) && EQ (propval, XCAR (tem)))
28869 return NILP (XCDR (tem)) ? 1 : 2;
28870 }
28871
28872 if (CONSP (propval))
28873 {
28874 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
28875 {
28876 Lisp_Object propelt;
28877 propelt = XCAR (proptail);
28878 for (tail = list; CONSP (tail); tail = XCDR (tail))
28879 {
28880 register Lisp_Object tem;
28881 tem = XCAR (tail);
28882 if (EQ (propelt, tem))
28883 return 1;
28884 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
28885 return NILP (XCDR (tem)) ? 1 : 2;
28886 }
28887 }
28888 }
28889
28890 return 0;
28891 }
28892
28893 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
28894 doc:
28895
28896
28897
28898
28899
28900
28901
28902
28903
28904
28905
28906 )
28907 (Lisp_Object pos)
28908 {
28909 Lisp_Object prop
28910 = (FIXNATP (pos) || MARKERP (pos)
28911 ? Fget_char_property (pos, Qinvisible, Qnil)
28912 : pos);
28913 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
28914 return (invis == 0 ? Qnil
28915 : invis == 1 ? Qt
28916 : make_fixnum (invis));
28917 }
28918
28919
28920
28921
28922
28923
28924
28925
28926
28927
28928
28929
28930
28931
28932
28933
28934
28935
28936
28937
28938
28939
28940
28941
28942
28943
28944
28945
28946
28947
28948
28949
28950
28951
28952
28953
28954
28955
28956
28957
28958
28959
28960
28961
28962
28963
28964
28965
28966
28967
28968
28969
28970
28971
28972
28973
28974
28975
28976
28977
28978
28979
28980
28981
28982
28983
28984
28985
28986
28987
28988
28989
28990
28991
28992
28993
28994
28995
28996
28997
28998
28999 static bool
29000 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
29001 struct font *font, bool width_p, int *align_to)
29002 {
29003
29004
29005
29006
29007 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
29008 double pixels;
29009
29010 # define OK_PIXELS(val) (*res = (val), true)
29011 # define OK_ALIGN_TO(val) (*align_to = (val), true)
29012
29013 if (NILP (prop))
29014 return OK_PIXELS (0);
29015
29016 eassert (FRAME_LIVE_P (it->f));
29017
29018 if (SYMBOLP (prop))
29019 {
29020 if (SCHARS (SYMBOL_NAME (prop)) == 2)
29021 {
29022 char *unit = SSDATA (SYMBOL_NAME (prop));
29023
29024
29025 if (unit[0] == 'i' && unit[1] == 'n')
29026 pixels = 1.0;
29027 else if (unit[0] == 'm' && unit[1] == 'm')
29028 pixels = 25.4;
29029 else if (unit[0] == 'c' && unit[1] == 'm')
29030 pixels = 2.54;
29031 else
29032 pixels = 0;
29033 if (pixels > 0)
29034 {
29035 double ppi = (width_p ? FRAME_RES_X (it->f)
29036 : FRAME_RES_Y (it->f));
29037
29038 if (ppi > 0)
29039 return OK_PIXELS (ppi / pixels);
29040 return false;
29041 }
29042 }
29043
29044 #ifdef HAVE_WINDOW_SYSTEM
29045
29046 if (EQ (prop, Qheight))
29047 return OK_PIXELS (font
29048 ? normal_char_height (font, -1)
29049 : FRAME_LINE_HEIGHT (it->f));
29050
29051 if (EQ (prop, Qwidth))
29052 return OK_PIXELS (font
29053 ? FONT_WIDTH (font)
29054 : FRAME_COLUMN_WIDTH (it->f));
29055 #else
29056 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
29057 return OK_PIXELS (1);
29058 #endif
29059
29060
29061 if (EQ (prop, Qtext))
29062 return OK_PIXELS (width_p
29063 ? (window_box_width (it->w, TEXT_AREA)
29064 - lnum_pixel_width)
29065 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
29066
29067
29068
29069
29070 if (align_to && *align_to < 0)
29071 {
29072 *res = 0;
29073
29074 if (EQ (prop, Qleft))
29075 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29076 + lnum_pixel_width);
29077
29078 if (EQ (prop, Qright))
29079 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
29080
29081 if (EQ (prop, Qcenter))
29082 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29083 + lnum_pixel_width
29084 + window_box_width (it->w, TEXT_AREA) / 2);
29085
29086 if (EQ (prop, Qleft_fringe))
29087 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29088 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29089 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29090
29091 if (EQ (prop, Qright_fringe))
29092 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29093 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29094 : window_box_right_offset (it->w, TEXT_AREA));
29095
29096 if (EQ (prop, Qleft_margin))
29097 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29098
29099 if (EQ (prop, Qright_margin))
29100 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29101
29102 if (EQ (prop, Qscroll_bar))
29103 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29104 ? 0
29105 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29106 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29107 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29108 : 0)));
29109 }
29110 else
29111 {
29112
29113 if (EQ (prop, Qleft_fringe))
29114 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29115 if (EQ (prop, Qright_fringe))
29116 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29117 if (EQ (prop, Qleft_margin))
29118 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29119 if (EQ (prop, Qright_margin))
29120 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29121 if (EQ (prop, Qscroll_bar))
29122 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29123 }
29124
29125 prop = buffer_local_value (prop, it->w->contents);
29126 if (BASE_EQ (prop, Qunbound))
29127 prop = Qnil;
29128 }
29129
29130 if (NUMBERP (prop))
29131 {
29132 int base_unit = (width_p
29133 ? FRAME_COLUMN_WIDTH (it->f)
29134 : FRAME_LINE_HEIGHT (it->f));
29135 if (width_p && align_to && *align_to < 0)
29136 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29137 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29138 }
29139
29140 if (CONSP (prop))
29141 {
29142 Lisp_Object car = XCAR (prop);
29143 Lisp_Object cdr = XCDR (prop);
29144
29145 if (SYMBOLP (car))
29146 {
29147 #ifdef HAVE_WINDOW_SYSTEM
29148
29149 if (FRAME_WINDOW_P (it->f)
29150 && valid_image_p (prop))
29151 {
29152 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29153 struct image *img = IMAGE_FROM_ID (it->f, id);
29154
29155 return OK_PIXELS (width_p ? img->width : img->height);
29156 }
29157
29158 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29159 {
29160
29161 return OK_PIXELS (100);
29162 }
29163 #endif
29164
29165
29166 if (EQ (car, Qplus) || EQ (car, Qminus))
29167 {
29168 bool first = true;
29169 double px;
29170
29171 pixels = 0;
29172 while (CONSP (cdr))
29173 {
29174 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29175 font, width_p, align_to))
29176 return false;
29177 if (first)
29178 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29179 else
29180 pixels += px;
29181 cdr = XCDR (cdr);
29182 }
29183 if (EQ (car, Qminus))
29184 pixels = -pixels;
29185 return OK_PIXELS (pixels);
29186 }
29187
29188 car = buffer_local_value (car, it->w->contents);
29189 if (BASE_EQ (car, Qunbound))
29190 car = Qnil;
29191 }
29192
29193
29194 if (NUMBERP (car))
29195 {
29196 double fact;
29197 int offset =
29198 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29199 pixels = XFLOATINT (car);
29200 if (NILP (cdr))
29201 return OK_PIXELS (pixels + offset);
29202 if (calc_pixel_width_or_height (&fact, it, cdr,
29203 font, width_p, align_to))
29204 return OK_PIXELS (pixels * fact + offset);
29205 return false;
29206 }
29207
29208 return false;
29209 }
29210
29211 return false;
29212 }
29213
29214 void
29215 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29216 {
29217 #ifdef HAVE_WINDOW_SYSTEM
29218 normal_char_ascent_descent (font, -1, ascent, descent);
29219 #else
29220 *ascent = 1;
29221 *descent = 0;
29222 #endif
29223 }
29224
29225
29226
29227
29228
29229
29230 #ifdef HAVE_WINDOW_SYSTEM
29231
29232 #ifdef GLYPH_DEBUG
29233
29234 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29235 void
29236 dump_glyph_string (struct glyph_string *s)
29237 {
29238 fputs ("glyph string\n", stderr);
29239 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29240 s->x, s->y, s->width, s->height);
29241 fprintf (stderr, " ybase = %d\n", s->ybase);
29242 fprintf (stderr, " hl = %u\n", s->hl);
29243 fprintf (stderr, " left overhang = %d, right = %d\n",
29244 s->left_overhang, s->right_overhang);
29245 fprintf (stderr, " nchars = %d\n", s->nchars);
29246 fprintf (stderr, " extends to end of line = %d\n",
29247 s->extends_to_end_of_line_p);
29248 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29249 fprintf (stderr, " bg width = %d\n", s->background_width);
29250 }
29251
29252 #endif
29253
29254
29255
29256
29257
29258
29259
29260
29261
29262 #ifdef HAVE_NTGUI
29263
29264
29265
29266
29267
29268 # define ALLOCATE_HDC(hdc, f) \
29269 Lisp_Object prev_quit = Vinhibit_quit; \
29270 Vinhibit_quit = Qt; \
29271 HDC hdc = get_frame_dc ((f))
29272 # define RELEASE_HDC(hdc, f) \
29273 release_frame_dc ((f), (hdc)); \
29274 Vinhibit_quit = prev_quit
29275 #else
29276 # define ALLOCATE_HDC(hdc, f)
29277 # define RELEASE_HDC(hdc, f)
29278 #endif
29279
29280 static void
29281 init_glyph_string (struct glyph_string *s,
29282 #ifdef HAVE_NTGUI
29283 HDC hdc,
29284 #endif
29285 unsigned *char2b, struct window *w, struct glyph_row *row,
29286 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29287 {
29288 memset (s, 0, sizeof *s);
29289 s->w = w;
29290 s->f = XFRAME (w->frame);
29291 #ifdef HAVE_NTGUI
29292 s->hdc = hdc;
29293 #endif
29294 s->char2b = char2b;
29295 s->hl = hl;
29296 s->row = row;
29297 s->area = area;
29298 s->first_glyph = row->glyphs[area] + start;
29299 s->height = row->height;
29300 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29301 s->ybase = s->y + row->ascent;
29302 }
29303
29304
29305
29306
29307
29308 static void
29309 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29310 struct glyph_string *h, struct glyph_string *t)
29311 {
29312 if (h)
29313 {
29314 if (*head)
29315 (*tail)->next = h;
29316 else
29317 *head = h;
29318 h->prev = *tail;
29319 *tail = t;
29320 }
29321 }
29322
29323
29324
29325
29326
29327
29328 static void
29329 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29330 struct glyph_string *h, struct glyph_string *t)
29331 {
29332 if (h)
29333 {
29334 if (*head)
29335 (*head)->prev = t;
29336 else
29337 *tail = t;
29338 t->next = *head;
29339 *head = h;
29340 }
29341 }
29342
29343
29344
29345
29346
29347 static void
29348 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29349 struct glyph_string *s)
29350 {
29351 s->next = s->prev = NULL;
29352 append_glyph_string_lists (head, tail, s, s);
29353 }
29354
29355
29356
29357
29358
29359
29360
29361
29362 static struct face *
29363 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29364 unsigned *char2b, bool display_p)
29365 {
29366 struct face *face = FACE_FROM_ID (f, face_id);
29367 unsigned code = 0;
29368
29369 if (face->font)
29370 {
29371 code = face->font->driver->encode_char (face->font, c);
29372
29373 if (code == FONT_INVALID_CODE)
29374 code = 0;
29375 }
29376
29377 *char2b = code & 0xFFFF;
29378
29379
29380 #ifdef HAVE_X_WINDOWS
29381 if (display_p)
29382 #endif
29383 {
29384 eassert (face != NULL);
29385 prepare_face_for_display (f, face);
29386 }
29387
29388 return face;
29389 }
29390
29391
29392
29393
29394
29395
29396 static struct face *
29397 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29398 unsigned *char2b)
29399 {
29400 struct face *face;
29401 unsigned code = 0;
29402
29403 eassert (glyph->type == CHAR_GLYPH);
29404 face = FACE_FROM_ID (f, glyph->face_id);
29405
29406
29407 prepare_face_for_display (f, face);
29408
29409 if (face->font)
29410 {
29411 if (CHAR_BYTE8_P (glyph->u.ch))
29412 code = CHAR_TO_BYTE8 (glyph->u.ch);
29413 else
29414 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29415
29416 if (code == FONT_INVALID_CODE)
29417 code = 0;
29418 }
29419
29420
29421 *char2b = code & 0xFFFF;
29422 return face;
29423 }
29424
29425
29426
29427
29428
29429 static bool
29430 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29431 {
29432 unsigned code;
29433
29434 if (CHAR_BYTE8_P (c))
29435 code = CHAR_TO_BYTE8 (c);
29436 else
29437 code = font->driver->encode_char (font, c);
29438
29439 if (code == FONT_INVALID_CODE)
29440 return false;
29441
29442
29443 *char2b = code & 0xFFFF;
29444 return true;
29445 }
29446
29447
29448
29449
29450
29451
29452
29453
29454
29455
29456
29457
29458 static int
29459 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29460 int overlaps)
29461 {
29462 int i;
29463
29464
29465
29466 struct face *face;
29467
29468 eassert (s);
29469
29470 s->for_overlaps = overlaps;
29471 s->face = NULL;
29472 s->font = NULL;
29473 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29474 {
29475 int c = COMPOSITION_GLYPH (s->cmp, i);
29476
29477
29478
29479 if (c != '\t')
29480 {
29481 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29482 -1, Qnil);
29483
29484 face = get_char_face_and_encoding (s->f, c, face_id,
29485 s->char2b + i, true);
29486 if (face)
29487 {
29488 if (! s->face)
29489 {
29490 s->face = face;
29491 s->font = s->face->font;
29492 }
29493 else if (s->face != face)
29494 break;
29495 }
29496 }
29497 ++s->nchars;
29498 }
29499 s->cmp_to = i;
29500
29501 if (s->face == NULL)
29502 {
29503 s->face = base_face->ascii_face;
29504 s->font = s->face->font;
29505 }
29506
29507 if (s->hl == DRAW_MOUSE_FACE
29508 || (s->hl == DRAW_CURSOR
29509 && MATRIX_ROW (s->w->current_matrix,
29510 s->w->phys_cursor.vpos)->mouse_face_p
29511 && cursor_in_mouse_face_p (s->w)))
29512 {
29513 int c = COMPOSITION_GLYPH (s->cmp, 0);
29514 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29515 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29516 if (!s->face)
29517 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29518
29519 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29520 prepare_face_for_display (s->f, s->face);
29521 }
29522
29523
29524
29525 s->width = s->first_glyph->pixel_width;
29526
29527
29528
29529
29530
29531 if (s->font == NULL)
29532 {
29533 s->font_not_found_p = true;
29534 s->font = FRAME_FONT (s->f);
29535 }
29536
29537
29538 s->ybase += s->first_glyph->voffset;
29539
29540 return s->cmp_to;
29541 }
29542
29543 static int
29544 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29545 int start, int end, int overlaps)
29546 {
29547 struct glyph *glyph, *last;
29548 int voffset;
29549 Lisp_Object lgstring;
29550 int i;
29551 bool glyph_not_available_p;
29552
29553 s->for_overlaps = overlaps;
29554 glyph = s->row->glyphs[s->area] + start;
29555 last = s->row->glyphs[s->area] + end;
29556 voffset = glyph->voffset;
29557 glyph_not_available_p = glyph->glyph_not_available_p;
29558 s->cmp_id = glyph->u.cmp.id;
29559 s->cmp_from = glyph->slice.cmp.from;
29560 s->cmp_to = glyph->slice.cmp.to + 1;
29561 if (s->hl == DRAW_MOUSE_FACE
29562 || (s->hl == DRAW_CURSOR
29563 && MATRIX_ROW (s->w->current_matrix,
29564 s->w->phys_cursor.vpos)->mouse_face_p
29565 && cursor_in_mouse_face_p (s->w)))
29566 {
29567 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29568 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29569 if (!s->face)
29570 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29571 prepare_face_for_display (s->f, s->face);
29572 }
29573 else
29574 s->face = FACE_FROM_ID (s->f, face_id);
29575 lgstring = composition_gstring_from_id (s->cmp_id);
29576 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29577
29578
29579 s->width = s->first_glyph->pixel_width;
29580 glyph++;
29581 while (glyph < last
29582 && glyph->u.cmp.automatic
29583 && glyph->u.cmp.id == s->cmp_id
29584 && glyph->face_id == face_id
29585 && s->cmp_to == glyph->slice.cmp.from
29586 && glyph->glyph_not_available_p == glyph_not_available_p)
29587 {
29588 s->width += glyph->pixel_width;
29589 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29590 }
29591
29592 for (i = s->cmp_from; i < s->cmp_to; i++)
29593 {
29594 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29595 unsigned code = LGLYPH_CODE (lglyph);
29596
29597
29598 s->char2b[i] = code & 0xFFFF;
29599 }
29600
29601
29602
29603
29604 if (glyph_not_available_p)
29605 s->font_not_found_p = true;
29606
29607
29608 s->ybase += voffset;
29609
29610 return glyph - s->row->glyphs[s->area];
29611 }
29612
29613
29614
29615
29616
29617
29618
29619 static int
29620 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29621 int start, int end, int overlaps)
29622 {
29623 struct glyph *glyph, *last;
29624 int voffset;
29625
29626 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29627 s->for_overlaps = overlaps;
29628 glyph = s->row->glyphs[s->area] + start;
29629 last = s->row->glyphs[s->area] + end;
29630 voffset = glyph->voffset;
29631 s->face = FACE_FROM_ID (s->f, face_id);
29632 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29633 if (s->hl == DRAW_MOUSE_FACE
29634 || (s->hl == DRAW_CURSOR
29635 && MATRIX_ROW (s->w->current_matrix,
29636 s->w->phys_cursor.vpos)->mouse_face_p
29637 && cursor_in_mouse_face_p (s->w)))
29638 {
29639 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29640 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29641 if (!s->face)
29642 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29643 prepare_face_for_display (s->f, s->face);
29644 }
29645 s->nchars = 1;
29646 s->width = glyph->pixel_width;
29647 glyph++;
29648 while (glyph < last
29649 && glyph->type == GLYPHLESS_GLYPH
29650 && glyph->voffset == voffset
29651 && glyph->face_id == face_id)
29652 {
29653 s->nchars++;
29654 s->width += glyph->pixel_width;
29655 glyph++;
29656 }
29657 s->ybase += voffset;
29658 return glyph - s->row->glyphs[s->area];
29659 }
29660
29661
29662
29663
29664
29665
29666
29667
29668
29669
29670
29671 static int
29672 fill_glyph_string (struct glyph_string *s, int face_id,
29673 int start, int end, int overlaps)
29674 {
29675 struct glyph *glyph, *last;
29676 int voffset;
29677 bool glyph_not_available_p;
29678
29679 eassert (s->f == XFRAME (s->w->frame));
29680 eassert (s->nchars == 0);
29681 eassert (start >= 0 && end > start);
29682
29683 s->for_overlaps = overlaps;
29684 glyph = s->row->glyphs[s->area] + start;
29685 last = s->row->glyphs[s->area] + end;
29686 voffset = glyph->voffset;
29687 s->padding_p = glyph->padding_p;
29688 glyph_not_available_p = glyph->glyph_not_available_p;
29689
29690 while (glyph < last
29691 && glyph->type == CHAR_GLYPH
29692 && glyph->voffset == voffset
29693
29694 && glyph->face_id == face_id
29695 && glyph->glyph_not_available_p == glyph_not_available_p)
29696 {
29697 s->face = get_glyph_face_and_encoding (s->f, glyph,
29698 s->char2b + s->nchars);
29699 ++s->nchars;
29700 eassert (s->nchars <= end - start);
29701 s->width += glyph->pixel_width;
29702 if (glyph++->padding_p != s->padding_p)
29703 break;
29704 }
29705
29706 s->font = s->face->font;
29707
29708 if (s->hl == DRAW_MOUSE_FACE
29709 || (s->hl == DRAW_CURSOR
29710 && MATRIX_ROW (s->w->current_matrix,
29711 s->w->phys_cursor.vpos)->mouse_face_p
29712 && cursor_in_mouse_face_p (s->w)))
29713 {
29714 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29715 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29716 if (!s->face)
29717 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29718 s->face
29719 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29720 s->first_glyph->u.ch, -1, Qnil));
29721 prepare_face_for_display (s->f, s->face);
29722 }
29723
29724
29725
29726
29727
29728 if (s->font == NULL || glyph_not_available_p)
29729 {
29730 s->font_not_found_p = true;
29731 s->font = FRAME_FONT (s->f);
29732 }
29733
29734
29735 s->ybase += voffset;
29736
29737 eassert (s->face && s->face->gc);
29738 return glyph - s->row->glyphs[s->area];
29739 }
29740
29741
29742
29743
29744 static void
29745 fill_image_glyph_string (struct glyph_string *s)
29746 {
29747 eassert (s->first_glyph->type == IMAGE_GLYPH);
29748 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29749 eassert (s->img);
29750 s->slice = s->first_glyph->slice.img;
29751 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29752 s->font = s->face->font;
29753 if (s->hl == DRAW_MOUSE_FACE
29754 || (s->hl == DRAW_CURSOR
29755 && MATRIX_ROW (s->w->current_matrix,
29756 s->w->phys_cursor.vpos)->mouse_face_p
29757 && cursor_in_mouse_face_p (s->w)))
29758 {
29759 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29760 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29761 if (!s->face)
29762 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29763 prepare_face_for_display (s->f, s->face);
29764 }
29765 s->width = s->first_glyph->pixel_width;
29766
29767
29768 s->ybase += s->first_glyph->voffset;
29769 }
29770
29771
29772 #ifdef HAVE_XWIDGETS
29773 static void
29774 fill_xwidget_glyph_string (struct glyph_string *s)
29775 {
29776 eassert (s->first_glyph->type == XWIDGET_GLYPH);
29777 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29778 s->font = s->face->font;
29779 if (s->hl == DRAW_MOUSE_FACE
29780 || (s->hl == DRAW_CURSOR
29781 && MATRIX_ROW (s->w->current_matrix,
29782 s->w->phys_cursor.vpos)->mouse_face_p
29783 && cursor_in_mouse_face_p (s->w)))
29784 {
29785 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29786 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29787 if (!s->face)
29788 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29789 prepare_face_for_display (s->f, s->face);
29790 }
29791 s->width = s->first_glyph->pixel_width;
29792 s->ybase += s->first_glyph->voffset;
29793 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
29794 }
29795 #endif
29796
29797
29798
29799
29800
29801
29802
29803 static int
29804 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
29805 {
29806 struct glyph *glyph, *last;
29807 int voffset, face_id;
29808
29809 eassert (s->first_glyph->type == STRETCH_GLYPH);
29810
29811 glyph = s->row->glyphs[s->area] + start;
29812 last = s->row->glyphs[s->area] + end;
29813 face_id = glyph->face_id;
29814 s->face = FACE_FROM_ID (s->f, face_id);
29815 s->font = s->face->font;
29816 if (s->hl == DRAW_MOUSE_FACE
29817 || (s->hl == DRAW_CURSOR
29818 && MATRIX_ROW (s->w->current_matrix,
29819 s->w->phys_cursor.vpos)->mouse_face_p
29820 && cursor_in_mouse_face_p (s->w)))
29821 {
29822 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29823 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29824 if (!s->face)
29825 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29826 prepare_face_for_display (s->f, s->face);
29827 }
29828 s->width = glyph->pixel_width;
29829 s->nchars = 1;
29830 voffset = glyph->voffset;
29831
29832 for (++glyph;
29833 (glyph < last
29834 && glyph->type == STRETCH_GLYPH
29835 && glyph->voffset == voffset
29836 && glyph->face_id == face_id);
29837 ++glyph)
29838 s->width += glyph->pixel_width;
29839
29840
29841 s->ybase += voffset;
29842
29843
29844
29845 eassert (s->face);
29846 return glyph - s->row->glyphs[s->area];
29847 }
29848
29849 static struct font_metrics *
29850 get_per_char_metric (struct font *font, const unsigned *char2b)
29851 {
29852 static struct font_metrics metrics;
29853
29854 if (! font)
29855 return NULL;
29856 if (*char2b == FONT_INVALID_CODE)
29857 return NULL;
29858
29859 font->driver->text_extents (font, char2b, 1, &metrics);
29860 return &metrics;
29861 }
29862
29863
29864
29865
29866
29867
29868
29869 static void
29870 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
29871 {
29872 *ascent = FONT_BASE (font);
29873 *descent = FONT_DESCENT (font);
29874
29875 if (FONT_TOO_HIGH (font))
29876 {
29877 unsigned char2b;
29878
29879
29880
29881 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
29882 {
29883 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
29884 eassume (pcm);
29885
29886 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
29887 {
29888
29889
29890
29891 *ascent = pcm->ascent + 1;
29892 *descent = pcm->descent + 1;
29893 }
29894 }
29895 }
29896 }
29897
29898
29899
29900
29901
29902
29903 static int
29904 normal_char_height (struct font *font, int c)
29905 {
29906 int ascent, descent;
29907
29908 normal_char_ascent_descent (font, c, &ascent, &descent);
29909
29910 return ascent + descent;
29911 }
29912
29913
29914
29915
29916
29917
29918 void
29919 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
29920 {
29921 *left = *right = 0;
29922
29923 if (glyph->type == CHAR_GLYPH)
29924 {
29925 unsigned char2b;
29926 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
29927 if (face->font)
29928 {
29929 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
29930 if (pcm)
29931 {
29932 if (pcm->rbearing > pcm->width)
29933 *right = pcm->rbearing - pcm->width;
29934 if (pcm->lbearing < 0)
29935 *left = -pcm->lbearing;
29936 }
29937 }
29938 }
29939 else if (glyph->type == COMPOSITE_GLYPH)
29940 {
29941 if (! glyph->u.cmp.automatic)
29942 {
29943 struct composition *cmp = composition_table[glyph->u.cmp.id];
29944
29945 if (cmp->rbearing > cmp->pixel_width)
29946 *right = cmp->rbearing - cmp->pixel_width;
29947 if (cmp->lbearing < 0)
29948 *left = - cmp->lbearing;
29949 }
29950 else
29951 {
29952 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
29953 struct font_metrics metrics;
29954
29955 composition_gstring_width (gstring, glyph->slice.cmp.from,
29956 glyph->slice.cmp.to + 1, &metrics);
29957 if (metrics.rbearing > metrics.width)
29958 *right = metrics.rbearing - metrics.width;
29959 if (metrics.lbearing < 0)
29960 *left = - metrics.lbearing;
29961 }
29962 }
29963 }
29964
29965
29966
29967
29968
29969
29970 static int
29971 left_overwritten (struct glyph_string *s)
29972 {
29973 int k;
29974
29975 if (s->left_overhang)
29976 {
29977 int x = 0, i;
29978 struct glyph *glyphs = s->row->glyphs[s->area];
29979 int first = s->first_glyph - glyphs;
29980
29981 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
29982 x -= glyphs[i].pixel_width;
29983
29984 k = i + 1;
29985 }
29986 else
29987 k = -1;
29988
29989 return k;
29990 }
29991
29992
29993
29994
29995
29996
29997 static int
29998 left_overwriting (struct glyph_string *s)
29999 {
30000 int i, k, x;
30001 struct glyph *glyphs = s->row->glyphs[s->area];
30002 int first = s->first_glyph - glyphs;
30003
30004 k = -1;
30005 x = 0;
30006 for (i = first - 1; i >= 0; --i)
30007 {
30008 int left, right;
30009 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30010 if (x + right > 0)
30011 k = i;
30012 x -= glyphs[i].pixel_width;
30013 }
30014
30015 return k;
30016 }
30017
30018
30019
30020
30021
30022
30023 static int
30024 right_overwritten (struct glyph_string *s)
30025 {
30026 int k = -1;
30027
30028 if (s->right_overhang)
30029 {
30030 int x = 0, i;
30031 struct glyph *glyphs = s->row->glyphs[s->area];
30032 int first = (s->first_glyph - glyphs
30033 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30034 int end = s->row->used[s->area];
30035
30036 for (i = first; i < end && s->right_overhang > x; ++i)
30037 x += glyphs[i].pixel_width;
30038
30039 k = i;
30040 }
30041
30042 return k;
30043 }
30044
30045
30046
30047
30048
30049
30050 static int
30051 right_overwriting (struct glyph_string *s)
30052 {
30053 int i, k, x;
30054 int end = s->row->used[s->area];
30055 struct glyph *glyphs = s->row->glyphs[s->area];
30056 int first = (s->first_glyph - glyphs
30057 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30058
30059 k = -1;
30060 x = 0;
30061 for (i = first; i < end; ++i)
30062 {
30063 int left, right;
30064 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30065 if (x - left < 0)
30066 k = i;
30067 x += glyphs[i].pixel_width;
30068 }
30069
30070 return k;
30071 }
30072
30073
30074
30075
30076
30077
30078
30079
30080
30081
30082
30083 static void
30084 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30085 {
30086
30087
30088
30089 if (start == s->row->used[s->area]
30090 && ((s->row->fill_line_p
30091 && (s->hl == DRAW_NORMAL_TEXT
30092 || s->hl == DRAW_IMAGE_RAISED
30093 || s->hl == DRAW_IMAGE_SUNKEN))
30094 || s->hl == DRAW_MOUSE_FACE))
30095 s->extends_to_end_of_line_p = true;
30096
30097
30098
30099
30100 if (s->extends_to_end_of_line_p)
30101 s->background_width = last_x - s->x + 1;
30102 else
30103 {
30104 s->background_width = s->width;
30105 #ifdef HAVE_WINDOW_SYSTEM
30106 if (FRAME_WINDOW_P (s->f)
30107 && s->hl == DRAW_CURSOR
30108 && MATRIX_ROW (s->w->current_matrix,
30109 s->w->phys_cursor.vpos)->mouse_face_p
30110 && cursor_in_mouse_face_p (s->w))
30111 {
30112
30113
30114
30115
30116 struct glyph *g = s->first_glyph;
30117 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30118 s->background_width +=
30119 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30120 regular_face, s->face);
30121
30122 s->width = s->background_width;
30123 }
30124 #endif
30125 }
30126 }
30127
30128
30129
30130
30131
30132 static struct glyph_string *
30133 glyph_string_containing_background_width (struct glyph_string *s)
30134 {
30135 if (s->cmp)
30136 while (s->cmp_from)
30137 s = s->prev;
30138
30139 return s;
30140 }
30141
30142
30143
30144
30145
30146
30147 static void
30148 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30149 {
30150 if (backward_p)
30151 {
30152 while (s)
30153 {
30154 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30155 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30156 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30157 x -= s->width;
30158 s->x = x;
30159 s = s->prev;
30160 }
30161 }
30162 else
30163 {
30164 while (s)
30165 {
30166 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30167 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30168 s->x = x;
30169 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30170 x += s->width;
30171 s = s->next;
30172 }
30173 }
30174 }
30175
30176
30177
30178
30179
30180
30181
30182
30183
30184 #ifdef HAVE_NTGUI
30185
30186
30187 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30188 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30189 #else
30190 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30191 init_glyph_string (s, char2b, w, row, area, start, hl)
30192 #endif
30193
30194
30195
30196
30197
30198
30199
30200
30201
30202
30203
30204 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30205 do \
30206 { \
30207 s = alloca (sizeof *s); \
30208 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30209 START = fill_stretch_glyph_string (s, START, END); \
30210 append_glyph_string (&HEAD, &TAIL, s); \
30211 s->x = (X); \
30212 } \
30213 while (false)
30214
30215
30216
30217
30218
30219
30220
30221
30222
30223
30224 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30225 do \
30226 { \
30227 s = alloca (sizeof *s); \
30228 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30229 fill_image_glyph_string (s); \
30230 append_glyph_string (&HEAD, &TAIL, s); \
30231 ++START; \
30232 s->x = (X); \
30233 } \
30234 while (false)
30235
30236 #ifndef HAVE_XWIDGETS
30237 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30238 eassume (false)
30239 #else
30240 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30241 do \
30242 { \
30243 s = alloca (sizeof *s); \
30244 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30245 fill_xwidget_glyph_string (s); \
30246 append_glyph_string (&(HEAD), &(TAIL), s); \
30247 ++(START); \
30248 s->x = (X); \
30249 } \
30250 while (false)
30251 #endif
30252
30253
30254
30255
30256
30257
30258
30259
30260
30261
30262 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30263 do \
30264 { \
30265 int face_id; \
30266 unsigned *char2b; \
30267 \
30268 face_id = (row)->glyphs[area][START].face_id; \
30269 \
30270 s = alloca (sizeof *s); \
30271 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30272 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30273 append_glyph_string (&HEAD, &TAIL, s); \
30274 s->x = (X); \
30275 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30276 } \
30277 while (false)
30278
30279
30280
30281
30282
30283
30284
30285
30286
30287
30288
30289 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30290 do { \
30291 int face_id = (row)->glyphs[area][START].face_id; \
30292 struct face *base_face = FACE_FROM_ID (f, face_id); \
30293 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30294 struct composition *cmp = composition_table[cmp_id]; \
30295 unsigned *char2b; \
30296 struct glyph_string *first_s = NULL; \
30297 int n; \
30298 \
30299 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30300 \
30301
30302 \
30303 for (n = 0; n < cmp->glyph_len;) \
30304 { \
30305 s = alloca (sizeof *s); \
30306 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30307 append_glyph_string (&(HEAD), &(TAIL), s); \
30308 s->cmp = cmp; \
30309 s->cmp_from = n; \
30310 s->x = (X); \
30311 if (n == 0) \
30312 first_s = s; \
30313 n = fill_composite_glyph_string (s, base_face, overlaps); \
30314 } \
30315 \
30316 ++START; \
30317 s = first_s; \
30318 } while (false)
30319
30320
30321
30322
30323
30324 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30325 do { \
30326 int face_id; \
30327 unsigned *char2b; \
30328 Lisp_Object gstring; \
30329 \
30330 face_id = (row)->glyphs[area][START].face_id; \
30331 gstring = (composition_gstring_from_id \
30332 ((row)->glyphs[area][START].u.cmp.id)); \
30333 s = alloca (sizeof *s); \
30334 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30335 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30336 append_glyph_string (&(HEAD), &(TAIL), s); \
30337 s->x = (X); \
30338 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30339 } while (false)
30340
30341
30342
30343
30344
30345
30346 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30347 do \
30348 { \
30349 int face_id; \
30350 \
30351 face_id = (row)->glyphs[area][START].face_id; \
30352 \
30353 s = alloca (sizeof *s); \
30354 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30355 append_glyph_string (&HEAD, &TAIL, s); \
30356 s->x = (X); \
30357 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30358 overlaps); \
30359 } \
30360 while (false)
30361
30362
30363
30364
30365
30366
30367
30368
30369
30370
30371
30372
30373 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30374 do \
30375 { \
30376 HEAD = TAIL = NULL; \
30377 while (START < END) \
30378 { \
30379 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30380 switch (first_glyph->type) \
30381 { \
30382 case CHAR_GLYPH: \
30383 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30384 HL, X, LAST_X); \
30385 break; \
30386 \
30387 case COMPOSITE_GLYPH: \
30388 if (first_glyph->u.cmp.automatic) \
30389 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30390 HL, X, LAST_X); \
30391 else \
30392 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30393 HL, X, LAST_X); \
30394 break; \
30395 \
30396 case STRETCH_GLYPH: \
30397 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30398 HL, X, LAST_X); \
30399 break; \
30400 \
30401 case IMAGE_GLYPH: \
30402 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30403 HL, X, LAST_X); \
30404 break;
30405
30406 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30407 case XWIDGET_GLYPH: \
30408 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30409 HL, X, LAST_X); \
30410 break;
30411
30412 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30413 case GLYPHLESS_GLYPH: \
30414 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30415 HL, X, LAST_X); \
30416 break; \
30417 \
30418 default: \
30419 emacs_abort (); \
30420 } \
30421 \
30422 if (s) \
30423 { \
30424 set_glyph_string_background_width (s, START, LAST_X); \
30425 (X) += s->width; \
30426 } \
30427 } \
30428 } while (false)
30429
30430
30431 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30432 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30433 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30434 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30435
30436
30437
30438
30439
30440
30441
30442
30443
30444
30445
30446
30447
30448
30449
30450
30451
30452
30453
30454
30455
30456
30457
30458
30459 static int
30460 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30461 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30462 enum draw_glyphs_face hl, int overlaps)
30463 {
30464 struct glyph_string *head, *tail;
30465 struct glyph_string *s;
30466 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30467 int i, j, x_reached, last_x, area_left = 0;
30468 struct frame *f = XFRAME (WINDOW_FRAME (w));
30469
30470 ALLOCATE_HDC (hdc, f);
30471
30472
30473 end = min (end, row->used[area]);
30474 start = clip_to_bounds (0, start, end);
30475
30476
30477
30478 if (row->full_width_p)
30479 {
30480
30481
30482 area_left = WINDOW_LEFT_EDGE_X (w);
30483 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30484 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30485 }
30486 else
30487 {
30488 area_left = window_box_left (w, area);
30489 last_x = area_left + window_box_width (w, area);
30490 }
30491 x += area_left;
30492
30493
30494
30495
30496
30497 i = start;
30498 USE_SAFE_ALLOCA;
30499 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30500 if (tail)
30501 {
30502 s = glyph_string_containing_background_width (tail);
30503 x_reached = s->x + s->background_width;
30504 }
30505 else
30506 x_reached = x;
30507
30508
30509
30510
30511 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30512 {
30513 struct glyph_string *h, *t;
30514 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30515 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30516 bool check_mouse_face = false;
30517 int dummy_x = 0;
30518
30519
30520
30521 if (area == TEXT_AREA && row->mouse_face_p
30522 && hlinfo->mouse_face_beg_row >= 0
30523 && hlinfo->mouse_face_end_row >= 0)
30524 {
30525 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30526
30527 if (row_vpos >= hlinfo->mouse_face_beg_row
30528 && row_vpos <= hlinfo->mouse_face_end_row)
30529 {
30530 check_mouse_face = true;
30531 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30532 ? hlinfo->mouse_face_beg_col : 0;
30533 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30534 ? hlinfo->mouse_face_end_col
30535 : row->used[TEXT_AREA];
30536 }
30537 }
30538
30539
30540 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30541 for (s = head; s; s = s->next)
30542 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30543
30544
30545
30546
30547
30548
30549 i = left_overwritten (head);
30550 if (i >= 0)
30551 {
30552 enum draw_glyphs_face overlap_hl;
30553
30554
30555
30556
30557
30558
30559
30560
30561 if (check_mouse_face
30562 && mouse_beg_col < start && mouse_end_col > i)
30563 overlap_hl = DRAW_MOUSE_FACE;
30564 else
30565 overlap_hl = DRAW_NORMAL_TEXT;
30566
30567 if (hl != overlap_hl)
30568 clip_head = head;
30569 j = i;
30570 BUILD_GLYPH_STRINGS (j, start, h, t,
30571 overlap_hl, dummy_x, last_x);
30572 start = i;
30573 compute_overhangs_and_x (t, head->x, true);
30574 prepend_glyph_string_lists (&head, &tail, h, t);
30575 if (clip_head == NULL)
30576 clip_head = head;
30577 }
30578
30579
30580
30581
30582
30583
30584
30585
30586 i = left_overwriting (head);
30587 if (i >= 0)
30588 {
30589 enum draw_glyphs_face overlap_hl;
30590
30591 if (check_mouse_face
30592 && mouse_beg_col < start && mouse_end_col > i)
30593 overlap_hl = DRAW_MOUSE_FACE;
30594 else
30595 overlap_hl = DRAW_NORMAL_TEXT;
30596
30597 if (hl == overlap_hl || clip_head == NULL)
30598 clip_head = head;
30599 BUILD_GLYPH_STRINGS (i, start, h, t,
30600 overlap_hl, dummy_x, last_x);
30601 for (s = h; s; s = s->next)
30602 s->background_filled_p = true;
30603 compute_overhangs_and_x (t, head->x, true);
30604 prepend_glyph_string_lists (&head, &tail, h, t);
30605 }
30606
30607
30608
30609
30610
30611 i = right_overwritten (tail);
30612 if (i >= 0)
30613 {
30614 enum draw_glyphs_face overlap_hl;
30615
30616 if (check_mouse_face
30617 && mouse_beg_col < i && mouse_end_col > end)
30618 overlap_hl = DRAW_MOUSE_FACE;
30619 else
30620 overlap_hl = DRAW_NORMAL_TEXT;
30621
30622 if (hl != overlap_hl)
30623 clip_tail = tail;
30624 BUILD_GLYPH_STRINGS (end, i, h, t,
30625 overlap_hl, x, last_x);
30626
30627
30628 compute_overhangs_and_x (h, tail->x + tail->width, false);
30629 append_glyph_string_lists (&head, &tail, h, t);
30630 if (clip_tail == NULL)
30631 clip_tail = tail;
30632 }
30633
30634
30635
30636
30637
30638
30639 i = right_overwriting (tail);
30640 if (i >= 0)
30641 {
30642 enum draw_glyphs_face overlap_hl;
30643 if (check_mouse_face
30644 && mouse_beg_col < i && mouse_end_col > end)
30645 overlap_hl = DRAW_MOUSE_FACE;
30646 else
30647 overlap_hl = DRAW_NORMAL_TEXT;
30648
30649 if (hl == overlap_hl || clip_tail == NULL)
30650 clip_tail = tail;
30651 i++;
30652 BUILD_GLYPH_STRINGS (end, i, h, t,
30653 overlap_hl, x, last_x);
30654 for (s = h; s; s = s->next)
30655 s->background_filled_p = true;
30656 compute_overhangs_and_x (h, tail->x + tail->width, false);
30657 append_glyph_string_lists (&head, &tail, h, t);
30658 }
30659 tail = glyph_string_containing_background_width (tail);
30660 if (clip_tail)
30661 clip_tail = glyph_string_containing_background_width (clip_tail);
30662 if (clip_head || clip_tail)
30663 for (s = head; s; s = s->next)
30664 {
30665 s->clip_head = clip_head;
30666 s->clip_tail = clip_tail;
30667 }
30668 }
30669
30670
30671 for (s = head; s; s = s->next)
30672 FRAME_RIF (f)->draw_glyph_string (s);
30673
30674
30675
30676 if (area == TEXT_AREA
30677 && !row->full_width_p
30678
30679
30680
30681 && !overlaps)
30682 {
30683 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30684 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30685 : (tail ? tail->x + tail->background_width : x));
30686 x0 -= area_left;
30687 x1 -= area_left;
30688
30689 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30690 row->y, MATRIX_ROW_BOTTOM_Y (row));
30691 }
30692
30693
30694
30695 if (row->full_width_p)
30696 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30697 else
30698 x_reached -= area_left;
30699
30700 RELEASE_HDC (hdc, f);
30701
30702 SAFE_FREE ();
30703 return x_reached;
30704 }
30705
30706
30707
30708
30709
30710
30711
30712
30713 struct font *
30714 font_for_underline_metrics (struct glyph_string *s)
30715 {
30716 struct glyph *g0 = s->row->glyphs[s->area], *g;
30717
30718 for (g = s->first_glyph - 1; g >= g0; g--)
30719 {
30720 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30721 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30722 break;
30723 }
30724
30725
30726 if (g == s->first_glyph - 1)
30727 return s->font;
30728 else
30729 {
30730
30731
30732 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30733 }
30734 }
30735
30736
30737
30738
30739 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30740 { \
30741 if (!it->f->fonts_changed \
30742 && (it->glyph_row->glyphs[area] \
30743 < it->glyph_row->glyphs[area + 1])) \
30744 { \
30745 it->w->ncols_scale_factor++; \
30746 it->f->fonts_changed = true; \
30747 } \
30748 }
30749
30750
30751
30752
30753 static void
30754 append_glyph (struct it *it)
30755 {
30756 struct glyph *glyph;
30757 enum glyph_row_area area = it->area;
30758
30759 eassert (it->glyph_row);
30760 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
30761
30762 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30763 if (glyph < it->glyph_row->glyphs[area + 1])
30764 {
30765
30766
30767 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30768 {
30769 struct glyph *g;
30770
30771
30772 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
30773 g[1] = *g;
30774 glyph = it->glyph_row->glyphs[area];
30775 }
30776 glyph->charpos = CHARPOS (it->position);
30777 glyph->object = it->object;
30778 if (it->pixel_width > 0)
30779 {
30780 eassert (it->pixel_width <= SHRT_MAX);
30781 glyph->pixel_width = it->pixel_width;
30782 glyph->padding_p = false;
30783 }
30784 else
30785 {
30786
30787
30788 glyph->pixel_width = 1;
30789 glyph->padding_p = true;
30790 }
30791 glyph->ascent = it->ascent;
30792 glyph->descent = it->descent;
30793 glyph->voffset = it->voffset;
30794 glyph->type = CHAR_GLYPH;
30795 glyph->avoid_cursor_p = it->avoid_cursor_p;
30796 glyph->multibyte_p = it->multibyte_p;
30797 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30798 {
30799
30800
30801 glyph->right_box_line_p = it->start_of_box_run_p;
30802 glyph->left_box_line_p = it->end_of_box_run_p;
30803 }
30804 else
30805 {
30806 glyph->left_box_line_p = it->start_of_box_run_p;
30807 glyph->right_box_line_p = it->end_of_box_run_p;
30808 }
30809 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30810 || it->phys_descent > it->descent);
30811 glyph->glyph_not_available_p = it->glyph_not_available_p;
30812 glyph->face_id = it->face_id;
30813 glyph->u.ch = it->char_to_display;
30814 glyph->slice.img = null_glyph_slice;
30815 glyph->font_type = FONT_TYPE_UNKNOWN;
30816 if (it->bidi_p)
30817 {
30818 glyph->resolved_level = it->bidi_it.resolved_level;
30819 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30820 glyph->bidi_type = it->bidi_it.type;
30821 }
30822 else
30823 {
30824 glyph->resolved_level = 0;
30825 glyph->bidi_type = UNKNOWN_BT;
30826 }
30827 ++it->glyph_row->used[area];
30828 }
30829 else
30830 IT_EXPAND_MATRIX_WIDTH (it, area);
30831 }
30832
30833
30834
30835
30836 static void
30837 append_composite_glyph (struct it *it)
30838 {
30839 struct glyph *glyph;
30840 enum glyph_row_area area = it->area;
30841
30842 eassert (it->glyph_row);
30843
30844 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30845 if (glyph < it->glyph_row->glyphs[area + 1])
30846 {
30847
30848
30849 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
30850 {
30851 struct glyph *g;
30852
30853
30854 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
30855 g[1] = *g;
30856 glyph = it->glyph_row->glyphs[it->area];
30857 }
30858 glyph->charpos = it->cmp_it.charpos;
30859 glyph->object = it->object;
30860 eassert (it->pixel_width <= SHRT_MAX);
30861 glyph->pixel_width = it->pixel_width;
30862 glyph->ascent = it->ascent;
30863 glyph->descent = it->descent;
30864 glyph->voffset = it->voffset;
30865 glyph->type = COMPOSITE_GLYPH;
30866 if (it->cmp_it.ch < 0)
30867 {
30868 glyph->u.cmp.automatic = false;
30869 glyph->u.cmp.id = it->cmp_it.id;
30870 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
30871 }
30872 else
30873 {
30874 glyph->u.cmp.automatic = true;
30875 glyph->u.cmp.id = it->cmp_it.id;
30876 glyph->slice.cmp.from = it->cmp_it.from;
30877 glyph->slice.cmp.to = it->cmp_it.to - 1;
30878 }
30879 glyph->avoid_cursor_p = it->avoid_cursor_p;
30880 glyph->multibyte_p = it->multibyte_p;
30881 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30882 {
30883
30884
30885 glyph->right_box_line_p = it->start_of_box_run_p;
30886 glyph->left_box_line_p = it->end_of_box_run_p;
30887 }
30888 else
30889 {
30890 glyph->left_box_line_p = it->start_of_box_run_p;
30891 glyph->right_box_line_p = it->end_of_box_run_p;
30892 }
30893 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30894 || it->phys_descent > it->descent);
30895 glyph->padding_p = false;
30896 glyph->glyph_not_available_p = it->glyph_not_available_p;
30897 glyph->face_id = it->face_id;
30898 glyph->font_type = FONT_TYPE_UNKNOWN;
30899 if (it->bidi_p)
30900 {
30901 glyph->resolved_level = it->bidi_it.resolved_level;
30902 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30903 glyph->bidi_type = it->bidi_it.type;
30904 }
30905 ++it->glyph_row->used[area];
30906 }
30907 else
30908 IT_EXPAND_MATRIX_WIDTH (it, area);
30909 }
30910
30911
30912
30913
30914
30915 static void
30916 take_vertical_position_into_account (struct it *it)
30917 {
30918 if (it->voffset)
30919 {
30920 if (it->voffset < 0)
30921
30922
30923 it->ascent -= it->voffset;
30924 else
30925
30926
30927 it->descent += it->voffset;
30928 }
30929 }
30930
30931
30932
30933
30934
30935
30936 static void
30937 produce_image_glyph (struct it *it)
30938 {
30939 struct image *img;
30940 struct face *face;
30941 int glyph_ascent, crop;
30942 struct glyph_slice slice;
30943
30944 eassert (it->what == IT_IMAGE);
30945
30946 face = FACE_FROM_ID (it->f, it->face_id);
30947
30948 prepare_face_for_display (it->f, face);
30949
30950 if (it->image_id < 0)
30951 {
30952
30953 it->ascent = it->phys_ascent = 0;
30954 it->descent = it->phys_descent = 0;
30955 it->pixel_width = 0;
30956 it->nglyphs = 0;
30957 return;
30958 }
30959
30960 img = IMAGE_FROM_ID (it->f, it->image_id);
30961
30962 prepare_image_for_display (it->f, img);
30963
30964 slice.x = slice.y = 0;
30965 slice.width = img->width;
30966 slice.height = img->height;
30967
30968 if (FIXNUMP (it->slice.x))
30969 slice.x = XFIXNUM (it->slice.x);
30970 else if (FLOATP (it->slice.x))
30971 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
30972
30973 if (FIXNUMP (it->slice.y))
30974 slice.y = XFIXNUM (it->slice.y);
30975 else if (FLOATP (it->slice.y))
30976 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
30977
30978 if (FIXNUMP (it->slice.width))
30979 slice.width = XFIXNUM (it->slice.width);
30980 else if (FLOATP (it->slice.width))
30981 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
30982
30983 if (FIXNUMP (it->slice.height))
30984 slice.height = XFIXNUM (it->slice.height);
30985 else if (FLOATP (it->slice.height))
30986 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
30987
30988 if (slice.x >= img->width)
30989 slice.x = img->width;
30990 if (slice.y >= img->height)
30991 slice.y = img->height;
30992 if (slice.x + slice.width >= img->width)
30993 slice.width = img->width - slice.x;
30994 if (slice.y + slice.height > img->height)
30995 slice.height = img->height - slice.y;
30996
30997 if (slice.width == 0 || slice.height == 0)
30998 return;
30999
31000 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
31001
31002 it->descent = slice.height - glyph_ascent;
31003 if (slice.y == 0)
31004 it->descent += img->vmargin;
31005 if (slice.y + slice.height == img->height)
31006 it->descent += img->vmargin;
31007 it->phys_descent = it->descent;
31008
31009 it->pixel_width = slice.width;
31010 if (slice.x == 0)
31011 it->pixel_width += img->hmargin;
31012 if (slice.x + slice.width == img->width)
31013 it->pixel_width += img->hmargin;
31014
31015
31016
31017 if (it->descent < 0)
31018 it->descent = 0;
31019
31020 it->nglyphs = 1;
31021
31022 if (face->box != FACE_NO_BOX)
31023 {
31024
31025
31026 if (face->box_horizontal_line_width > 0)
31027 {
31028 if (slice.y == 0)
31029 it->ascent += face->box_horizontal_line_width;
31030 if (slice.y + slice.height == img->height)
31031 it->descent += face->box_horizontal_line_width;
31032 }
31033
31034 if (face->box_vertical_line_width > 0)
31035 {
31036 if (it->start_of_box_run_p && slice.x == 0)
31037 it->pixel_width += face->box_vertical_line_width;
31038 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
31039 it->pixel_width += face->box_vertical_line_width;
31040 }
31041 }
31042
31043 take_vertical_position_into_account (it);
31044
31045
31046
31047 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
31048 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31049 {
31050 it->pixel_width -= crop;
31051 slice.width -= crop;
31052 }
31053
31054 if (it->glyph_row)
31055 {
31056 struct glyph *glyph;
31057 enum glyph_row_area area = it->area;
31058
31059 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31060 if (it->glyph_row->reversed_p)
31061 {
31062 struct glyph *g;
31063
31064
31065 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31066 g[1] = *g;
31067 glyph = it->glyph_row->glyphs[it->area];
31068 }
31069 if (glyph < it->glyph_row->glyphs[area + 1])
31070 {
31071 glyph->charpos = CHARPOS (it->position);
31072 glyph->object = it->object;
31073 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31074 glyph->ascent = glyph_ascent;
31075 glyph->descent = it->descent;
31076 glyph->voffset = it->voffset;
31077 glyph->type = IMAGE_GLYPH;
31078 glyph->avoid_cursor_p = it->avoid_cursor_p;
31079 glyph->multibyte_p = it->multibyte_p;
31080 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31081 {
31082
31083
31084 glyph->right_box_line_p = it->start_of_box_run_p;
31085 glyph->left_box_line_p = it->end_of_box_run_p;
31086 }
31087 else
31088 {
31089 glyph->left_box_line_p = it->start_of_box_run_p;
31090 glyph->right_box_line_p = it->end_of_box_run_p;
31091 }
31092 glyph->overlaps_vertically_p = false;
31093 glyph->padding_p = false;
31094 glyph->glyph_not_available_p = false;
31095 glyph->face_id = it->face_id;
31096 glyph->u.img_id = img->id;
31097 glyph->slice.img = slice;
31098 glyph->font_type = FONT_TYPE_UNKNOWN;
31099 if (it->bidi_p)
31100 {
31101 glyph->resolved_level = it->bidi_it.resolved_level;
31102 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31103 glyph->bidi_type = it->bidi_it.type;
31104 }
31105 ++it->glyph_row->used[area];
31106 }
31107 else
31108 IT_EXPAND_MATRIX_WIDTH (it, area);
31109 }
31110 }
31111
31112 static void
31113 produce_xwidget_glyph (struct it *it)
31114 {
31115 #ifdef HAVE_XWIDGETS
31116 struct xwidget *xw;
31117 int glyph_ascent, crop;
31118 eassert (it->what == IT_XWIDGET);
31119
31120 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31121
31122 prepare_face_for_display (it->f, face);
31123
31124 xw = it->xwidget;
31125 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31126 it->descent = xw->height/2;
31127 it->phys_descent = it->descent;
31128 it->pixel_width = xw->width;
31129
31130
31131 if (it->descent < 0)
31132 it->descent = 0;
31133
31134 it->nglyphs = 1;
31135
31136 if (face->box != FACE_NO_BOX)
31137 {
31138 if (face->box_horizontal_line_width > 0)
31139 {
31140 it->ascent += face->box_horizontal_line_width;
31141 it->descent += face->box_horizontal_line_width;
31142 }
31143
31144 if (face->box_vertical_line_width > 0)
31145 {
31146 if (it->start_of_box_run_p)
31147 it->pixel_width += face->box_vertical_line_width;
31148 it->pixel_width += face->box_vertical_line_width;
31149 }
31150 }
31151
31152 take_vertical_position_into_account (it);
31153
31154
31155
31156 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31157 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31158 it->pixel_width -= crop;
31159
31160 if (it->glyph_row)
31161 {
31162 enum glyph_row_area area = it->area;
31163 struct glyph *glyph
31164 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31165
31166 if (it->glyph_row->reversed_p)
31167 {
31168 struct glyph *g;
31169
31170
31171 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31172 g[1] = *g;
31173 glyph = it->glyph_row->glyphs[it->area];
31174 }
31175 if (glyph < it->glyph_row->glyphs[area + 1])
31176 {
31177 glyph->charpos = CHARPOS (it->position);
31178 glyph->object = it->object;
31179 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31180 glyph->ascent = glyph_ascent;
31181 glyph->descent = it->descent;
31182 glyph->voffset = it->voffset;
31183 glyph->type = XWIDGET_GLYPH;
31184 glyph->avoid_cursor_p = it->avoid_cursor_p;
31185 glyph->multibyte_p = it->multibyte_p;
31186 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31187 {
31188
31189
31190 glyph->right_box_line_p = it->start_of_box_run_p;
31191 glyph->left_box_line_p = it->end_of_box_run_p;
31192 }
31193 else
31194 {
31195 glyph->left_box_line_p = it->start_of_box_run_p;
31196 glyph->right_box_line_p = it->end_of_box_run_p;
31197 }
31198 glyph->overlaps_vertically_p = 0;
31199 glyph->padding_p = 0;
31200 glyph->glyph_not_available_p = 0;
31201 glyph->face_id = it->face_id;
31202 glyph->u.xwidget = it->xwidget->xwidget_id;
31203 glyph->font_type = FONT_TYPE_UNKNOWN;
31204 if (it->bidi_p)
31205 {
31206 glyph->resolved_level = it->bidi_it.resolved_level;
31207 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31208 glyph->bidi_type = it->bidi_it.type;
31209 }
31210 ++it->glyph_row->used[area];
31211 }
31212 else
31213 IT_EXPAND_MATRIX_WIDTH (it, area);
31214 }
31215 #endif
31216 }
31217
31218
31219
31220
31221
31222 static void
31223 append_stretch_glyph (struct it *it, Lisp_Object object,
31224 int width, int height, int ascent)
31225 {
31226 struct glyph *glyph;
31227 enum glyph_row_area area = it->area;
31228
31229 eassert (ascent >= 0 && ascent <= height);
31230
31231 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31232 if (glyph < it->glyph_row->glyphs[area + 1])
31233 {
31234
31235
31236 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31237 {
31238 struct glyph *g;
31239
31240
31241 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31242 g[1] = *g;
31243 glyph = it->glyph_row->glyphs[area];
31244
31245
31246
31247
31248
31249
31250
31251
31252
31253
31254
31255
31256
31257
31258
31259 if (it->current_x < it->first_visible_x)
31260 width -= it->first_visible_x - it->current_x;
31261 eassert (width > 0);
31262 }
31263 glyph->charpos = CHARPOS (it->position);
31264 glyph->object = object;
31265
31266
31267 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31268 glyph->ascent = ascent;
31269 glyph->descent = height - ascent;
31270 glyph->voffset = it->voffset;
31271 glyph->type = STRETCH_GLYPH;
31272 glyph->avoid_cursor_p = it->avoid_cursor_p;
31273 glyph->multibyte_p = it->multibyte_p;
31274 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31275 {
31276
31277
31278 glyph->right_box_line_p = it->start_of_box_run_p;
31279 glyph->left_box_line_p = it->end_of_box_run_p;
31280 }
31281 else
31282 {
31283 glyph->left_box_line_p = it->start_of_box_run_p;
31284 glyph->right_box_line_p = it->end_of_box_run_p;
31285 }
31286 glyph->overlaps_vertically_p = false;
31287 glyph->padding_p = false;
31288 glyph->glyph_not_available_p = false;
31289 glyph->face_id = it->face_id;
31290 glyph->u.stretch.ascent = ascent;
31291 glyph->u.stretch.height = height;
31292 glyph->slice.img = null_glyph_slice;
31293 glyph->font_type = FONT_TYPE_UNKNOWN;
31294 if (it->bidi_p)
31295 {
31296 glyph->resolved_level = it->bidi_it.resolved_level;
31297 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31298 glyph->bidi_type = it->bidi_it.type;
31299 }
31300 else
31301 {
31302 glyph->resolved_level = 0;
31303 glyph->bidi_type = UNKNOWN_BT;
31304 }
31305 ++it->glyph_row->used[area];
31306 }
31307 else
31308 IT_EXPAND_MATRIX_WIDTH (it, area);
31309 }
31310
31311 #endif
31312
31313
31314
31315
31316
31317
31318
31319
31320
31321
31322
31323
31324
31325
31326
31327
31328
31329
31330
31331
31332
31333
31334
31335
31336
31337
31338
31339
31340
31341
31342
31343
31344 void
31345 produce_stretch_glyph (struct it *it)
31346 {
31347
31348 Lisp_Object prop, plist;
31349 int width = 0, height = 0, align_to = -1;
31350 bool zero_width_ok_p = false;
31351 double tem;
31352 struct font *font = NULL;
31353
31354 #ifdef HAVE_WINDOW_SYSTEM
31355 int ascent = 0;
31356 bool zero_height_ok_p = false;
31357 struct face *face = NULL;
31358
31359 if (FRAME_WINDOW_P (it->f))
31360 {
31361 face = FACE_FROM_ID (it->f, it->face_id);
31362 font = face->font ? face->font : FRAME_FONT (it->f);
31363 prepare_face_for_display (it->f, face);
31364 }
31365 #endif
31366
31367
31368 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31369 plist = XCDR (it->object);
31370
31371
31372 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31373 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31374 {
31375
31376 zero_width_ok_p = true;
31377 width = (int)tem;
31378 }
31379 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31380 {
31381
31382
31383
31384 struct it it2;
31385 Lisp_Object object =
31386 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31387 unsigned char *p = (STRINGP (object)
31388 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31389 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31390 bool multibyte_p =
31391 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31392
31393 it2 = *it;
31394 if (multibyte_p)
31395 {
31396 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31397 #ifdef HAVE_WINDOW_SYSTEM
31398 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31399 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31400 IT_CHARPOS (*it),
31401 STRINGP (object)? object : Qnil);
31402 #endif
31403 }
31404 else
31405 {
31406 it2.c = it2.char_to_display = *p, it2.len = 1;
31407 if (! ASCII_CHAR_P (it2.c))
31408 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31409 }
31410
31411 it2.glyph_row = NULL;
31412 it2.what = IT_CHARACTER;
31413 PRODUCE_GLYPHS (&it2);
31414 width = NUMVAL (prop) * it2.pixel_width;
31415 }
31416 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31417 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31418 &align_to))
31419 {
31420 int x = it->current_x + it->continuation_lines_width;
31421 int x0 = x;
31422
31423 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31424 {
31425 x -= it->lnum_pixel_width;
31426
31427 if (x + it->stretch_adjust >= it->first_visible_x)
31428 x += it->stretch_adjust;
31429 }
31430
31431 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31432 align_to = (align_to < 0
31433 ? 0
31434 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31435 else if (align_to < 0)
31436 align_to = window_box_left_offset (it->w, TEXT_AREA);
31437 width = max (0, (int)tem + align_to - x);
31438
31439 int next_x = x + width;
31440 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31441 {
31442
31443
31444 if (x < it->first_visible_x)
31445 {
31446 next_x -= it->first_visible_x - x;
31447 it->stretch_adjust = it->first_visible_x - x;
31448 }
31449 else
31450 next_x -= it->stretch_adjust;
31451 }
31452 width = next_x - x0;
31453 zero_width_ok_p = true;
31454 }
31455 else
31456
31457 width = FRAME_COLUMN_WIDTH (it->f);
31458
31459 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31460 width = 1;
31461
31462 #ifdef HAVE_WINDOW_SYSTEM
31463
31464 if (FRAME_WINDOW_P (it->f))
31465 {
31466 int default_height = normal_char_height (font, ' ');
31467
31468 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31469 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31470 {
31471 height = (int)tem;
31472 zero_height_ok_p = true;
31473 }
31474 else if (prop = plist_get (plist, QCrelative_height),
31475 NUMVAL (prop) > 0)
31476 height = default_height * NUMVAL (prop);
31477 else
31478 height = default_height;
31479
31480 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31481 height = 1;
31482
31483
31484
31485
31486 if (prop = plist_get (plist, QCascent),
31487 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31488 ascent = height * NUMVAL (prop) / 100.0;
31489 else if (!NILP (prop)
31490 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31491 ascent = min (max (0, (int)tem), height);
31492 else
31493 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31494 }
31495 else
31496 #endif
31497 height = 1;
31498
31499 if (width > 0
31500 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31501 && it->current_x + width > it->last_visible_x)
31502 {
31503 width = it->last_visible_x - it->current_x;
31504 #ifdef HAVE_WINDOW_SYSTEM
31505
31506
31507 width -= FRAME_WINDOW_P (it->f);
31508 #endif
31509 }
31510
31511 if (width > 0 && height > 0 && it->glyph_row)
31512 {
31513 Lisp_Object o_object = it->object;
31514 Lisp_Object object =
31515 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31516 int n = width;
31517
31518 if (!STRINGP (object))
31519 object = it->w->contents;
31520 #ifdef HAVE_WINDOW_SYSTEM
31521 if (FRAME_WINDOW_P (it->f))
31522 append_stretch_glyph (it, object, width, height, ascent);
31523 else
31524 #endif
31525 {
31526 it->object = object;
31527 it->char_to_display = ' ';
31528 it->pixel_width = it->len = 1;
31529 while (n--)
31530 tty_append_glyph (it);
31531 it->object = o_object;
31532 }
31533 }
31534
31535 it->pixel_width = width;
31536 #ifdef HAVE_WINDOW_SYSTEM
31537 if (FRAME_WINDOW_P (it->f))
31538 {
31539 it->ascent = it->phys_ascent = ascent;
31540 it->descent = it->phys_descent = height - it->ascent;
31541 it->nglyphs = width > 0 && height > 0;
31542 take_vertical_position_into_account (it);
31543 }
31544 else
31545 #endif
31546 it->nglyphs = width;
31547 }
31548
31549
31550
31551
31552
31553
31554
31555 static void
31556 produce_special_glyphs (struct it *it, enum display_element_type what)
31557 {
31558 struct it temp_it;
31559 Lisp_Object gc;
31560 GLYPH glyph;
31561
31562 temp_it = *it;
31563 temp_it.object = Qnil;
31564 memset (&temp_it.current, 0, sizeof temp_it.current);
31565
31566 if (what == IT_CONTINUATION)
31567 {
31568
31569 if (it->bidi_it.paragraph_dir == R2L)
31570 SET_GLYPH_FROM_CHAR (glyph, '/');
31571 else
31572 SET_GLYPH_FROM_CHAR (glyph, '\\');
31573 if (it->dp
31574 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31575 {
31576
31577 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31578 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31579 }
31580 }
31581 else if (what == IT_TRUNCATION)
31582 {
31583
31584 SET_GLYPH_FROM_CHAR (glyph, '$');
31585 if (it->dp
31586 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31587 {
31588
31589 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31590 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31591 }
31592 }
31593 else
31594 emacs_abort ();
31595
31596 #ifdef HAVE_WINDOW_SYSTEM
31597
31598
31599
31600
31601
31602 if (FRAME_WINDOW_P (temp_it.f)
31603
31604
31605
31606 && temp_it.glyph_row
31607
31608
31609
31610 && temp_it.glyph_row->used[TEXT_AREA] > 0
31611 && (temp_it.glyph_row->reversed_p
31612 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31613 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31614 {
31615 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31616
31617 if (stretch_width > 0)
31618 {
31619 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31620 struct font *font =
31621 face->font ? face->font : FRAME_FONT (temp_it.f);
31622 int stretch_ascent =
31623 (((temp_it.ascent + temp_it.descent)
31624 * FONT_BASE (font)) / FONT_HEIGHT (font));
31625
31626 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31627 temp_it.ascent + temp_it.descent,
31628 stretch_ascent);
31629 }
31630 }
31631 #endif
31632
31633 temp_it.dp = NULL;
31634 temp_it.what = IT_CHARACTER;
31635 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31636 temp_it.face_id = GLYPH_FACE (glyph);
31637 temp_it.len = CHAR_BYTES (temp_it.c);
31638
31639 PRODUCE_GLYPHS (&temp_it);
31640 it->pixel_width = temp_it.pixel_width;
31641 it->nglyphs = temp_it.nglyphs;
31642 }
31643
31644
31645
31646
31647
31648
31649
31650
31651
31652 static void
31653 pad_mode_line (struct it *it, bool mode_line_p)
31654 {
31655 struct it temp_it;
31656 GLYPH glyph;
31657
31658 eassert (!FRAME_WINDOW_P (it->f));
31659 temp_it = *it;
31660 temp_it.object = Qnil;
31661 memset (&temp_it.current, 0, sizeof temp_it.current);
31662
31663 SET_GLYPH (glyph, mode_line_p ? '-' : ' ', it->base_face_id);
31664
31665 temp_it.dp = NULL;
31666 temp_it.what = IT_CHARACTER;
31667 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31668 temp_it.face_id = GLYPH_FACE (glyph);
31669 temp_it.len = CHAR_BYTES (temp_it.c);
31670
31671 PRODUCE_GLYPHS (&temp_it);
31672 it->pixel_width = temp_it.pixel_width;
31673 it->nglyphs = temp_it.nglyphs;
31674 }
31675
31676 #ifdef HAVE_WINDOW_SYSTEM
31677
31678
31679
31680
31681
31682
31683
31684
31685
31686 static Lisp_Object
31687 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31688 int boff, bool override)
31689 {
31690 Lisp_Object face_name = Qnil;
31691 int ascent, descent, height;
31692
31693 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31694 return val;
31695
31696 if (CONSP (val))
31697 {
31698 face_name = XCAR (val);
31699 val = XCDR (val);
31700 if (!NUMBERP (val))
31701 val = make_fixnum (1);
31702 if (NILP (face_name))
31703 {
31704 height = it->ascent + it->descent;
31705 goto scale;
31706 }
31707 }
31708
31709 if (NILP (face_name))
31710 {
31711 font = FRAME_FONT (it->f);
31712 boff = FRAME_BASELINE_OFFSET (it->f);
31713 }
31714 else if (EQ (face_name, Qt))
31715 {
31716 override = false;
31717 }
31718 else
31719 {
31720 int face_id;
31721 struct face *face;
31722
31723 face_id = lookup_named_face (it->w, it->f, face_name, false);
31724 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31725 if (face == NULL || ((font = face->font) == NULL))
31726 return make_fixnum (-1);
31727 boff = font->baseline_offset;
31728 if (font->vertical_centering)
31729 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31730 }
31731
31732 normal_char_ascent_descent (font, -1, &ascent, &descent);
31733
31734 if (override)
31735 {
31736 it->override_ascent = ascent;
31737 it->override_descent = descent;
31738 it->override_boff = boff;
31739 }
31740
31741 height = ascent + descent;
31742
31743 scale:
31744
31745 if (FLOATP (val))
31746 height = (int)(XFLOAT_DATA (val) * height);
31747 else if (INTEGERP (val))
31748 {
31749 intmax_t v;
31750 if (integer_to_intmax (val, &v))
31751 height *= v;
31752 }
31753
31754 return make_fixnum (height);
31755 }
31756
31757
31758
31759
31760
31761
31762
31763
31764
31765
31766
31767
31768
31769
31770 static void
31771 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
31772 short upper_xoff, short upper_yoff,
31773 short lower_xoff, short lower_yoff)
31774 {
31775 struct glyph *glyph;
31776 enum glyph_row_area area = it->area;
31777
31778 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31779 if (glyph < it->glyph_row->glyphs[area + 1])
31780 {
31781
31782
31783 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31784 {
31785 struct glyph *g;
31786
31787
31788 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31789 g[1] = *g;
31790 glyph = it->glyph_row->glyphs[area];
31791 }
31792 glyph->charpos = CHARPOS (it->position);
31793 glyph->object = it->object;
31794 eassert (it->pixel_width <= SHRT_MAX);
31795 glyph->pixel_width = it->pixel_width;
31796 glyph->ascent = it->ascent;
31797 glyph->descent = it->descent;
31798 glyph->voffset = it->voffset;
31799 glyph->type = GLYPHLESS_GLYPH;
31800 glyph->u.glyphless.method = it->glyphless_method;
31801 glyph->u.glyphless.for_no_font = for_no_font;
31802 glyph->u.glyphless.len = len;
31803 glyph->u.glyphless.ch = it->c;
31804 glyph->slice.glyphless.upper_xoff = upper_xoff;
31805 glyph->slice.glyphless.upper_yoff = upper_yoff;
31806 glyph->slice.glyphless.lower_xoff = lower_xoff;
31807 glyph->slice.glyphless.lower_yoff = lower_yoff;
31808 glyph->avoid_cursor_p = it->avoid_cursor_p;
31809 glyph->multibyte_p = it->multibyte_p;
31810 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31811 {
31812
31813
31814 glyph->right_box_line_p = it->start_of_box_run_p;
31815 glyph->left_box_line_p = it->end_of_box_run_p;
31816 }
31817 else
31818 {
31819 glyph->left_box_line_p = it->start_of_box_run_p;
31820 glyph->right_box_line_p = it->end_of_box_run_p;
31821 }
31822 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31823 || it->phys_descent > it->descent);
31824 glyph->padding_p = false;
31825 glyph->glyph_not_available_p = false;
31826 glyph->face_id = face_id;
31827 glyph->font_type = FONT_TYPE_UNKNOWN;
31828 if (it->bidi_p)
31829 {
31830 glyph->resolved_level = it->bidi_it.resolved_level;
31831 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31832 glyph->bidi_type = it->bidi_it.type;
31833 }
31834 ++it->glyph_row->used[area];
31835 }
31836 else
31837 IT_EXPAND_MATRIX_WIDTH (it, area);
31838 }
31839
31840
31841
31842
31843
31844
31845
31846
31847
31848
31849
31850 static void
31851 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
31852 {
31853 int face_id;
31854 struct face *face;
31855 struct font *font;
31856 int base_width, base_height, width, height;
31857 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
31858 int len;
31859
31860
31861
31862 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
31863 font = face->font ? face->font : FRAME_FONT (it->f);
31864 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
31865 it->ascent += font->baseline_offset;
31866 it->descent -= font->baseline_offset;
31867 base_height = it->ascent + it->descent;
31868 base_width = font->average_width;
31869
31870 face_id = merge_glyphless_glyph_face (it);
31871
31872 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
31873 {
31874 it->pixel_width = THIN_SPACE_WIDTH;
31875 len = 0;
31876 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
31877 }
31878 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
31879 {
31880 width = CHARACTER_WIDTH (it->c);
31881 if (width == 0)
31882 width = 1;
31883 else if (width > 4)
31884 width = 4;
31885 it->pixel_width = base_width * width;
31886 len = 0;
31887 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
31888 }
31889 else
31890 {
31891 char buf[7];
31892 const char *str;
31893 unsigned int code[6];
31894 int upper_len;
31895 int ascent, descent;
31896 struct font_metrics metrics_upper, metrics_lower;
31897
31898 face = FACE_FROM_ID (it->f, face_id);
31899 font = face->font ? face->font : FRAME_FONT (it->f);
31900 prepare_face_for_display (it->f, face);
31901
31902 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
31903 {
31904 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
31905 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
31906 if (CONSP (acronym))
31907 acronym = XCAR (acronym);
31908 str = STRINGP (acronym) ? SSDATA (acronym) : "";
31909 }
31910 else
31911 {
31912 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
31913 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
31914 str = buf;
31915 }
31916 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
31917 code[len] = font->driver->encode_char (font, str[len]);
31918 upper_len = (len + 1) / 2;
31919 font->driver->text_extents (font, code, upper_len,
31920 &metrics_upper);
31921 font->driver->text_extents (font, code + upper_len, len - upper_len,
31922 &metrics_lower);
31923
31924
31925
31926
31927 width = max (metrics_upper.width, metrics_lower.width) + 4;
31928 upper_xoff = lower_xoff = 2;
31929 if (base_width >= width)
31930 {
31931
31932 it->pixel_width = base_width;
31933 lower_xoff = base_width - 2 - metrics_lower.width;
31934 }
31935 else
31936 {
31937
31938 it->pixel_width = width;
31939 if (metrics_upper.width >= metrics_lower.width)
31940 lower_xoff = (width - metrics_lower.width) / 2;
31941 else
31942 upper_xoff = (width - metrics_upper.width) / 2;
31943 }
31944
31945
31946
31947 height = (metrics_upper.ascent + metrics_upper.descent
31948 + metrics_lower.ascent + metrics_lower.descent) + 5;
31949
31950
31951
31952
31953
31954
31955
31956
31957 ascent = - (it->descent - (base_height + height + 1) / 2);
31958 descent = it->descent - (base_height - height) / 2;
31959 lower_yoff = descent - 2 - metrics_lower.descent;
31960 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
31961 - metrics_upper.descent);
31962
31963 if (height > base_height)
31964 {
31965 it->ascent = ascent;
31966 it->descent = descent;
31967 }
31968 }
31969
31970 it->phys_ascent = it->ascent;
31971 it->phys_descent = it->descent;
31972 if (it->glyph_row)
31973 append_glyphless_glyph (it, face_id, for_no_font, len,
31974 upper_xoff, upper_yoff,
31975 lower_xoff, lower_yoff);
31976 it->nglyphs = 1;
31977 take_vertical_position_into_account (it);
31978 }
31979
31980
31981
31982
31983
31984 #define IT_APPLY_FACE_BOX(it, face) \
31985 do { \
31986 if (face->box != FACE_NO_BOX) \
31987 { \
31988 int thick = face->box_horizontal_line_width; \
31989 if (thick > 0) \
31990 { \
31991 it->ascent += thick; \
31992 it->descent += thick; \
31993 } \
31994 \
31995 thick = face->box_vertical_line_width; \
31996 if (thick > 0) \
31997 { \
31998 if (it->start_of_box_run_p) \
31999 it->pixel_width += thick; \
32000 if (it->end_of_box_run_p) \
32001 it->pixel_width += thick; \
32002 } \
32003 } \
32004 } while (false)
32005
32006
32007
32008
32009
32010
32011 void
32012 gui_produce_glyphs (struct it *it)
32013 {
32014 int extra_line_spacing = it->extra_line_spacing;
32015
32016 it->glyph_not_available_p = false;
32017
32018 if (it->what == IT_CHARACTER)
32019 {
32020 unsigned char2b;
32021 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32022 struct font *font = face->font;
32023 struct font_metrics *pcm = NULL;
32024 int boff;
32025
32026 if (font == NULL)
32027 {
32028
32029
32030
32031 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
32032
32033 eassert (it->what == IT_GLYPHLESS);
32034 produce_glyphless_glyph (it, true,
32035 STRINGP (acronym) ? acronym : Qnil);
32036 goto done;
32037 }
32038
32039 boff = font->baseline_offset;
32040 if (font->vertical_centering)
32041 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32042
32043 if (it->char_to_display != '\n' && it->char_to_display != '\t')
32044 {
32045 it->nglyphs = 1;
32046
32047 if (it->override_ascent >= 0)
32048 {
32049 it->ascent = it->override_ascent;
32050 it->descent = it->override_descent;
32051 boff = it->override_boff;
32052 }
32053 else
32054 {
32055 it->ascent = FONT_BASE (font) + boff;
32056 it->descent = FONT_DESCENT (font) - boff;
32057 }
32058
32059 if (get_char_glyph_code (it->char_to_display, font, &char2b))
32060 {
32061 pcm = get_per_char_metric (font, &char2b);
32062 if (pcm->width == 0
32063 && pcm->rbearing == 0 && pcm->lbearing == 0)
32064 pcm = NULL;
32065 }
32066
32067 if (pcm)
32068 {
32069 it->phys_ascent = pcm->ascent + boff;
32070 it->phys_descent = pcm->descent - boff;
32071 it->pixel_width = pcm->width;
32072
32073
32074 if (it->override_ascent < 0)
32075 {
32076 if (FONT_TOO_HIGH (font))
32077 {
32078 it->ascent = it->phys_ascent;
32079 it->descent = it->phys_descent;
32080
32081
32082 if (it->ascent < 0)
32083 it->ascent = 0;
32084 if (it->descent < 0)
32085 it->descent = 0;
32086 }
32087 }
32088 }
32089 else
32090 {
32091 it->glyph_not_available_p = true;
32092 it->phys_ascent = it->ascent;
32093 it->phys_descent = it->descent;
32094 it->pixel_width = font->space_width;
32095 }
32096
32097 if (it->constrain_row_ascent_descent_p)
32098 {
32099 if (it->descent > it->max_descent)
32100 {
32101 it->ascent += it->descent - it->max_descent;
32102 it->descent = it->max_descent;
32103 }
32104 if (it->ascent > it->max_ascent)
32105 {
32106 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32107 it->ascent = it->max_ascent;
32108 }
32109 it->phys_ascent = min (it->phys_ascent, it->ascent);
32110 it->phys_descent = min (it->phys_descent, it->descent);
32111 extra_line_spacing = 0;
32112 }
32113
32114
32115
32116 bool stretched_p
32117 = it->char_to_display == ' ' && !NILP (it->space_width);
32118 if (stretched_p)
32119 it->pixel_width *= XFLOATINT (it->space_width);
32120
32121 IT_APPLY_FACE_BOX(it, face);
32122
32123
32124
32125 if (face->overline_p)
32126 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32127
32128 if (it->constrain_row_ascent_descent_p)
32129 {
32130 if (it->ascent > it->max_ascent)
32131 it->ascent = it->max_ascent;
32132 if (it->descent > it->max_descent)
32133 it->descent = it->max_descent;
32134 }
32135
32136 take_vertical_position_into_account (it);
32137
32138
32139 if (it->glyph_row)
32140 {
32141 if (stretched_p)
32142 {
32143
32144
32145 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32146 / FONT_HEIGHT (font));
32147 append_stretch_glyph (it, it->object, it->pixel_width,
32148 it->ascent + it->descent, ascent);
32149 }
32150 else
32151 append_glyph (it);
32152
32153
32154
32155
32156 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32157 it->glyph_row->contains_overlapping_glyphs_p = true;
32158 }
32159 if (! stretched_p && it->pixel_width == 0)
32160
32161
32162 it->pixel_width = 1;
32163 }
32164 else if (it->char_to_display == '\n')
32165 {
32166
32167
32168
32169
32170 Lisp_Object height;
32171 Lisp_Object total_height = Qnil;
32172
32173 it->override_ascent = -1;
32174 it->pixel_width = 0;
32175 it->nglyphs = 0;
32176
32177 height = get_it_property (it, Qline_height);
32178
32179 if (CONSP (height)
32180 && CONSP (XCDR (height))
32181 && NILP (XCDR (XCDR (height))))
32182 {
32183 total_height = XCAR (XCDR (height));
32184 height = XCAR (height);
32185 }
32186 height = calc_line_height_property (it, height, font, boff, true);
32187
32188 if (it->override_ascent >= 0)
32189 {
32190 it->ascent = it->override_ascent;
32191 it->descent = it->override_descent;
32192 boff = it->override_boff;
32193 }
32194 else
32195 {
32196 if (FONT_TOO_HIGH (font))
32197 {
32198 it->ascent = font->pixel_size + boff - 1;
32199 it->descent = -boff + 1;
32200 if (it->descent < 0)
32201 it->descent = 0;
32202 }
32203 else
32204 {
32205 it->ascent = FONT_BASE (font) + boff;
32206 it->descent = FONT_DESCENT (font) - boff;
32207 }
32208 }
32209
32210 if (EQ (height, Qt))
32211 {
32212 if (it->descent > it->max_descent)
32213 {
32214 it->ascent += it->descent - it->max_descent;
32215 it->descent = it->max_descent;
32216 }
32217 if (it->ascent > it->max_ascent)
32218 {
32219 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32220 it->ascent = it->max_ascent;
32221 }
32222 it->phys_ascent = min (it->phys_ascent, it->ascent);
32223 it->phys_descent = min (it->phys_descent, it->descent);
32224 it->constrain_row_ascent_descent_p = true;
32225 extra_line_spacing = 0;
32226 }
32227 else
32228 {
32229 Lisp_Object spacing;
32230
32231 it->phys_ascent = it->ascent;
32232 it->phys_descent = it->descent;
32233
32234 if ((it->max_ascent > 0 || it->max_descent > 0)
32235 && face->box != FACE_NO_BOX
32236 && face->box_horizontal_line_width > 0)
32237 {
32238 it->ascent += face->box_horizontal_line_width;
32239 it->descent += face->box_horizontal_line_width;
32240 }
32241 if (!NILP (height)
32242 && XFIXNUM (height) > it->ascent + it->descent)
32243 it->ascent = XFIXNUM (height) - it->descent;
32244
32245 if (!NILP (total_height))
32246 spacing = calc_line_height_property (it, total_height, font,
32247 boff, false);
32248 else
32249 {
32250 spacing = get_it_property (it, Qline_spacing);
32251 spacing = calc_line_height_property (it, spacing, font,
32252 boff, false);
32253 }
32254 if (FIXNUMP (spacing))
32255 {
32256 extra_line_spacing = XFIXNUM (spacing);
32257 if (!NILP (total_height))
32258 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32259 }
32260 }
32261 }
32262 else
32263 {
32264 if (font->space_width > 0)
32265 {
32266 int tab_width = it->tab_width * font->space_width;
32267 int x = it->current_x + it->continuation_lines_width;
32268 int x0 = x;
32269
32270 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32271 {
32272 x -= it->lnum_pixel_width;
32273
32274 if (x + it->stretch_adjust >= it->first_visible_x)
32275 x += it->stretch_adjust;
32276 }
32277
32278 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32279
32280
32281
32282
32283 if (next_tab_x - x < font->space_width)
32284 next_tab_x += tab_width;
32285 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32286 {
32287 next_tab_x += it->lnum_pixel_width;
32288
32289
32290 if (x < it->first_visible_x)
32291 {
32292 next_tab_x -= it->first_visible_x - x;
32293 it->stretch_adjust = it->first_visible_x - x;
32294 }
32295 else
32296 next_tab_x -= it->stretch_adjust;
32297 }
32298
32299 it->pixel_width = next_tab_x - x0;
32300 it->nglyphs = 1;
32301 if (FONT_TOO_HIGH (font))
32302 {
32303 if (get_char_glyph_code (' ', font, &char2b))
32304 {
32305 pcm = get_per_char_metric (font, &char2b);
32306 if (pcm->width == 0
32307 && pcm->rbearing == 0 && pcm->lbearing == 0)
32308 pcm = NULL;
32309 }
32310
32311 if (pcm)
32312 {
32313 it->ascent = pcm->ascent + boff;
32314 it->descent = pcm->descent - boff;
32315 }
32316 else
32317 {
32318 it->ascent = font->pixel_size + boff - 1;
32319 it->descent = -boff + 1;
32320 }
32321 if (it->ascent < 0)
32322 it->ascent = 0;
32323 if (it->descent < 0)
32324 it->descent = 0;
32325 }
32326 else
32327 {
32328 it->ascent = FONT_BASE (font) + boff;
32329 it->descent = FONT_DESCENT (font) - boff;
32330 }
32331 it->phys_ascent = it->ascent;
32332 it->phys_descent = it->descent;
32333
32334 if (it->glyph_row)
32335 {
32336 append_stretch_glyph (it, it->object, it->pixel_width,
32337 it->ascent + it->descent, it->ascent);
32338 }
32339 }
32340 else
32341 {
32342 it->pixel_width = 0;
32343 it->nglyphs = 1;
32344 }
32345 }
32346
32347 if (FONT_TOO_HIGH (font))
32348 {
32349 int font_ascent, font_descent;
32350
32351
32352
32353
32354
32355
32356
32357
32358 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32359 it->max_ascent = max (it->max_ascent, font_ascent);
32360 it->max_descent = max (it->max_descent, font_descent);
32361 }
32362
32363 if (it->ascent < 0)
32364 it->ascent = 0;
32365 if (it->descent < 0)
32366 it->descent = 0;
32367 }
32368 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32369 {
32370
32371
32372
32373
32374
32375
32376
32377
32378 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32379 int boff;
32380 struct composition *cmp = composition_table[it->cmp_it.id];
32381 int glyph_len = cmp->glyph_len;
32382 struct font *font = face->font;
32383
32384 it->nglyphs = 1;
32385
32386
32387
32388
32389
32390
32391
32392
32393 if (! cmp->font || cmp->font != font)
32394 {
32395
32396
32397
32398
32399 int font_ascent, font_descent, font_height;
32400
32401 int leftmost, rightmost, lowest, highest;
32402 int lbearing, rbearing;
32403 int i, width, ascent, descent;
32404 int c;
32405 unsigned char2b;
32406 struct font_metrics *pcm;
32407 ptrdiff_t pos;
32408
32409 eassume (0 < glyph_len);
32410 do
32411 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32412 while (c == '\t' && 0 < --glyph_len);
32413
32414 bool right_padded = glyph_len < cmp->glyph_len;
32415 for (i = 0; i < glyph_len; i++)
32416 {
32417 c = COMPOSITION_GLYPH (cmp, i);
32418 if (c != '\t')
32419 break;
32420 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32421 }
32422 bool left_padded = i > 0;
32423
32424 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32425 : IT_CHARPOS (*it));
32426
32427 bool font_not_found_p = font == NULL;
32428 if (font_not_found_p)
32429 {
32430 face = face->ascii_face;
32431 font = face->font;
32432 }
32433 boff = font->baseline_offset;
32434 if (font->vertical_centering)
32435 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32436 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32437 font_ascent += boff;
32438 font_descent -= boff;
32439 font_height = font_ascent + font_descent;
32440
32441 cmp->font = font;
32442
32443 pcm = NULL;
32444 if (! font_not_found_p)
32445 {
32446 get_char_face_and_encoding (it->f, c, it->face_id,
32447 &char2b, false);
32448 pcm = get_per_char_metric (font, &char2b);
32449 }
32450
32451
32452 if (pcm)
32453 {
32454 width = cmp->glyph_len > 0 ? pcm->width : 0;
32455 ascent = pcm->ascent;
32456 descent = pcm->descent;
32457 lbearing = pcm->lbearing;
32458 rbearing = pcm->rbearing;
32459 }
32460 else
32461 {
32462 width = cmp->glyph_len > 0 ? font->space_width : 0;
32463 ascent = FONT_BASE (font);
32464 descent = FONT_DESCENT (font);
32465 lbearing = 0;
32466 rbearing = width;
32467 }
32468
32469 rightmost = width;
32470 leftmost = 0;
32471 lowest = - descent + boff;
32472 highest = ascent + boff;
32473
32474 if (! font_not_found_p
32475 && font->default_ascent
32476 && CHAR_TABLE_P (Vuse_default_ascent)
32477 && !NILP (Faref (Vuse_default_ascent,
32478 make_fixnum (it->char_to_display))))
32479 highest = font->default_ascent + boff;
32480
32481
32482
32483
32484 cmp->offsets[i * 2] = 0;
32485 cmp->offsets[i * 2 + 1] = boff;
32486 cmp->lbearing = lbearing;
32487 cmp->rbearing = rbearing;
32488
32489
32490 for (i++; i < glyph_len; i++)
32491 {
32492 int left, right, btm, top;
32493 int ch = COMPOSITION_GLYPH (cmp, i);
32494 int face_id;
32495 struct face *this_face;
32496
32497 if (ch == '\t')
32498 ch = ' ';
32499 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32500 this_face = FACE_FROM_ID (it->f, face_id);
32501 font = this_face->font;
32502
32503 if (font == NULL)
32504 pcm = NULL;
32505 else
32506 {
32507 get_char_face_and_encoding (it->f, ch, face_id,
32508 &char2b, false);
32509 pcm = get_per_char_metric (font, &char2b);
32510 }
32511 if (! pcm)
32512 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32513 else
32514 {
32515 width = pcm->width;
32516 ascent = pcm->ascent;
32517 descent = pcm->descent;
32518 lbearing = pcm->lbearing;
32519 rbearing = pcm->rbearing;
32520 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32521 {
32522
32523
32524 left = (leftmost + rightmost - width) / 2;
32525 btm = - descent + boff;
32526 if (font->relative_compose
32527 && (! CHAR_TABLE_P (Vignore_relative_composition)
32528 || NILP (Faref (Vignore_relative_composition,
32529 make_fixnum (ch)))))
32530 {
32531
32532 if (- descent >= font->relative_compose)
32533
32534 btm = highest + 1;
32535 else if (ascent <= 0)
32536
32537 btm = lowest - 1 - ascent - descent;
32538 }
32539 }
32540 else
32541 {
32542
32543
32544
32545
32546
32547
32548
32549
32550
32551
32552
32553
32554
32555
32556
32557 int rule = COMPOSITION_RULE (cmp, i);
32558 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32559
32560 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32561 grefx = gref % 3, nrefx = nref % 3;
32562 grefy = gref / 3, nrefy = nref / 3;
32563 if (xoff)
32564 xoff = font_height * (xoff - 128) / 256;
32565 if (yoff)
32566 yoff = font_height * (yoff - 128) / 256;
32567
32568 left = (leftmost
32569 + grefx * (rightmost - leftmost) / 2
32570 - nrefx * width / 2
32571 + xoff);
32572
32573 btm = ((grefy == 0 ? highest
32574 : grefy == 1 ? 0
32575 : grefy == 2 ? lowest
32576 : (highest + lowest) / 2)
32577 - (nrefy == 0 ? ascent + descent
32578 : nrefy == 1 ? descent - boff
32579 : nrefy == 2 ? 0
32580 : (ascent + descent) / 2)
32581 + yoff);
32582 }
32583
32584 cmp->offsets[i * 2] = left;
32585 cmp->offsets[i * 2 + 1] = btm + descent;
32586
32587
32588 if (width > 0)
32589 {
32590 right = left + width;
32591 if (left < leftmost)
32592 leftmost = left;
32593 if (right > rightmost)
32594 rightmost = right;
32595 }
32596 top = btm + descent + ascent;
32597 if (top > highest)
32598 highest = top;
32599 if (btm < lowest)
32600 lowest = btm;
32601
32602 if (cmp->lbearing > left + lbearing)
32603 cmp->lbearing = left + lbearing;
32604 if (cmp->rbearing < left + rbearing)
32605 cmp->rbearing = left + rbearing;
32606 }
32607 }
32608
32609
32610
32611
32612 if (leftmost < 0)
32613 {
32614 for (i = 0; i < cmp->glyph_len; i++)
32615 cmp->offsets[i * 2] -= leftmost;
32616 rightmost -= leftmost;
32617 cmp->lbearing -= leftmost;
32618 cmp->rbearing -= leftmost;
32619 }
32620
32621 if (left_padded && cmp->lbearing < 0)
32622 {
32623 for (i = 0; i < cmp->glyph_len; i++)
32624 cmp->offsets[i * 2] -= cmp->lbearing;
32625 rightmost -= cmp->lbearing;
32626 cmp->rbearing -= cmp->lbearing;
32627 cmp->lbearing = 0;
32628 }
32629 if (right_padded && rightmost < cmp->rbearing)
32630 {
32631 rightmost = cmp->rbearing;
32632 }
32633
32634 cmp->pixel_width = rightmost;
32635 cmp->ascent = highest;
32636 cmp->descent = - lowest;
32637 if (cmp->ascent < font_ascent)
32638 cmp->ascent = font_ascent;
32639 if (cmp->descent < font_descent)
32640 cmp->descent = font_descent;
32641 }
32642
32643 if (it->glyph_row
32644 && (cmp->lbearing < 0
32645 || cmp->rbearing > cmp->pixel_width))
32646 it->glyph_row->contains_overlapping_glyphs_p = true;
32647
32648 it->pixel_width = cmp->pixel_width;
32649 it->ascent = it->phys_ascent = cmp->ascent;
32650 it->descent = it->phys_descent = cmp->descent;
32651 IT_APPLY_FACE_BOX(it, face);
32652
32653
32654
32655 if (face->overline_p)
32656 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32657
32658 take_vertical_position_into_account (it);
32659 if (it->ascent < 0)
32660 it->ascent = 0;
32661 if (it->descent < 0)
32662 it->descent = 0;
32663
32664 if (it->glyph_row && cmp->glyph_len > 0)
32665 append_composite_glyph (it);
32666 }
32667 else if (it->what == IT_COMPOSITION)
32668 {
32669
32670 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32671 Lisp_Object gstring;
32672 struct font_metrics metrics;
32673
32674 it->nglyphs = 1;
32675
32676 gstring = composition_gstring_from_id (it->cmp_it.id);
32677 it->pixel_width
32678 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32679 &metrics);
32680 if (it->pixel_width == 0)
32681 {
32682 it->glyph_not_available_p = true;
32683 it->phys_ascent = it->ascent;
32684 it->phys_descent = it->descent;
32685 it->pixel_width = face->font->space_width;
32686 }
32687 else
32688 {
32689 if (it->glyph_row
32690 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32691 it->glyph_row->contains_overlapping_glyphs_p = true;
32692 it->ascent = it->phys_ascent = metrics.ascent;
32693 it->descent = it->phys_descent = metrics.descent;
32694 }
32695 IT_APPLY_FACE_BOX(it, face);
32696
32697
32698
32699 if (face->overline_p)
32700 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32701 take_vertical_position_into_account (it);
32702 if (it->ascent < 0)
32703 it->ascent = 0;
32704 if (it->descent < 0)
32705 it->descent = 0;
32706
32707 if (it->glyph_row)
32708 append_composite_glyph (it);
32709 }
32710 else if (it->what == IT_GLYPHLESS)
32711 produce_glyphless_glyph (it, false, Qnil);
32712 else if (it->what == IT_IMAGE)
32713 produce_image_glyph (it);
32714 else if (it->what == IT_STRETCH)
32715 produce_stretch_glyph (it);
32716 else if (it->what == IT_XWIDGET)
32717 produce_xwidget_glyph (it);
32718
32719 done:
32720
32721
32722 eassert (it->ascent >= 0 && it->descent >= 0);
32723 if (it->area == TEXT_AREA)
32724 it->current_x += it->pixel_width;
32725
32726 if (extra_line_spacing > 0)
32727 {
32728 it->descent += extra_line_spacing;
32729 if (extra_line_spacing > it->max_extra_line_spacing)
32730 it->max_extra_line_spacing = extra_line_spacing;
32731 }
32732
32733 it->max_ascent = max (it->max_ascent, it->ascent);
32734 it->max_descent = max (it->max_descent, it->descent);
32735 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32736 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32737 }
32738
32739
32740
32741
32742
32743
32744 void
32745 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32746 struct glyph *start, enum glyph_row_area updated_area, int len)
32747 {
32748 int x, hpos, chpos = w->phys_cursor.hpos;
32749
32750 eassert (updated_row);
32751
32752
32753
32754 if (!updated_row->reversed_p && chpos < 0)
32755 chpos = 0;
32756 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
32757 chpos = updated_row->used[TEXT_AREA] - 1;
32758
32759 block_input ();
32760
32761
32762
32763 hpos = start - updated_row->glyphs[updated_area];
32764 x = draw_glyphs (w, w->output_cursor.x,
32765 updated_row, updated_area,
32766 hpos, hpos + len,
32767 DRAW_NORMAL_TEXT, 0);
32768
32769
32770 if (updated_area == TEXT_AREA
32771 && w->phys_cursor_on_p
32772 && w->phys_cursor.vpos == w->output_cursor.vpos
32773 && chpos >= hpos
32774 && chpos < hpos + len)
32775 w->phys_cursor_on_p = false;
32776
32777 unblock_input ();
32778
32779
32780 w->output_cursor.hpos += len;
32781 w->output_cursor.x = x;
32782 }
32783
32784
32785
32786
32787
32788 void
32789 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
32790 struct glyph *start, enum glyph_row_area updated_area, int len)
32791 {
32792 struct frame *f;
32793 int line_height, shift_by_width, shifted_region_width;
32794 struct glyph_row *row;
32795 struct glyph *glyph;
32796 int frame_x, frame_y;
32797 ptrdiff_t hpos;
32798
32799 eassert (updated_row);
32800 block_input ();
32801 f = XFRAME (WINDOW_FRAME (w));
32802
32803
32804 row = updated_row;
32805 line_height = row->height;
32806
32807
32808 shift_by_width = 0;
32809 for (glyph = start; glyph < start + len; ++glyph)
32810 shift_by_width += glyph->pixel_width;
32811
32812
32813 shifted_region_width = (window_box_width (w, updated_area)
32814 - w->output_cursor.x
32815 - shift_by_width);
32816
32817
32818 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
32819 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
32820
32821 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
32822 line_height, shift_by_width);
32823
32824
32825 hpos = start - row->glyphs[updated_area];
32826 draw_glyphs (w, w->output_cursor.x, row, updated_area,
32827 hpos, hpos + len,
32828 DRAW_NORMAL_TEXT, 0);
32829
32830
32831 w->output_cursor.hpos += len;
32832 w->output_cursor.x += shift_by_width;
32833 unblock_input ();
32834 }
32835
32836
32837
32838
32839
32840
32841
32842
32843
32844
32845 void
32846 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
32847 enum glyph_row_area updated_area, int to_x)
32848 {
32849 struct frame *f;
32850 int max_x, min_y, max_y;
32851 int from_x, from_y, to_y;
32852 struct face *face;
32853
32854 eassert (updated_row);
32855 f = XFRAME (w->frame);
32856 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
32857
32858 if (updated_row->full_width_p)
32859 max_x = (WINDOW_PIXEL_WIDTH (w)
32860 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
32861 else
32862 max_x = window_box_width (w, updated_area);
32863 max_y = window_text_bottom_y (w);
32864
32865
32866
32867 if (to_x == 0)
32868 return;
32869 else if (to_x < 0)
32870 to_x = max_x;
32871 else
32872 to_x = min (to_x, max_x);
32873
32874 to_y = min (max_y, w->output_cursor.y + updated_row->height);
32875
32876
32877 if (!updated_row->full_width_p)
32878 notice_overwritten_cursor (w, updated_area,
32879 w->output_cursor.x, -1,
32880 updated_row->y,
32881 MATRIX_ROW_BOTTOM_Y (updated_row));
32882
32883 from_x = w->output_cursor.x;
32884
32885
32886 if (updated_row->full_width_p)
32887 {
32888 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
32889 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
32890 }
32891 else
32892 {
32893 int area_left = window_box_left (w, updated_area);
32894 from_x += area_left;
32895 to_x += area_left;
32896 }
32897
32898 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
32899 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
32900 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
32901
32902
32903 if (to_x > from_x && to_y > from_y)
32904 {
32905 block_input ();
32906 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
32907 to_x - from_x, to_y - from_y);
32908
32909 if (face && !updated_row->stipple_p)
32910 updated_row->stipple_p = face->stipple;
32911 unblock_input ();
32912 }
32913 }
32914
32915 #endif
32916
32917
32918
32919
32920
32921
32922
32923
32924
32925
32926
32927 static enum text_cursor_kinds
32928 get_specified_cursor_type (Lisp_Object arg, int *width)
32929 {
32930 enum text_cursor_kinds type;
32931
32932 if (NILP (arg))
32933 return NO_CURSOR;
32934
32935 if (EQ (arg, Qbox))
32936 return FILLED_BOX_CURSOR;
32937
32938 if (EQ (arg, Qhollow))
32939 return HOLLOW_BOX_CURSOR;
32940
32941 if (EQ (arg, Qbar))
32942 {
32943 *width = 2;
32944 return BAR_CURSOR;
32945 }
32946
32947 if (EQ (arg, Qhbar))
32948 {
32949 *width = 2;
32950 return HBAR_CURSOR;
32951 }
32952
32953 if (CONSP (arg)
32954 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
32955 {
32956 *width = XFIXNUM (XCDR (arg));
32957
32958 if (EQ (XCAR (arg), Qbox))
32959 return FILLED_BOX_CURSOR;
32960 else if (EQ (XCAR (arg), Qbar))
32961 return BAR_CURSOR;
32962 else if (EQ (XCAR (arg), Qhbar))
32963 return HBAR_CURSOR;
32964 }
32965
32966
32967
32968
32969 type = HOLLOW_BOX_CURSOR;
32970
32971 return type;
32972 }
32973
32974
32975 void
32976 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
32977 {
32978 int width = 1;
32979 Lisp_Object tem;
32980
32981 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
32982 FRAME_CURSOR_WIDTH (f) = width;
32983
32984
32985
32986 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
32987 if (!NILP (tem))
32988 {
32989 FRAME_BLINK_OFF_CURSOR (f)
32990 = get_specified_cursor_type (XCDR (tem), &width);
32991 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
32992 }
32993 else
32994 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
32995
32996
32997 f->cursor_type_changed = true;
32998 }
32999
33000
33001 #ifdef HAVE_WINDOW_SYSTEM
33002
33003
33004
33005
33006
33007
33008
33009
33010
33011
33012
33013
33014 static enum text_cursor_kinds
33015 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
33016 bool *active_cursor)
33017 {
33018 struct frame *f = XFRAME (w->frame);
33019 struct buffer *b = XBUFFER (w->contents);
33020 int cursor_type = DEFAULT_CURSOR;
33021 Lisp_Object alt_cursor;
33022 bool non_selected = false;
33023
33024 *active_cursor = true;
33025
33026
33027 if (cursor_in_echo_area
33028 && FRAME_HAS_MINIBUF_P (f)
33029 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
33030 {
33031 if (w == XWINDOW (echo_area_window))
33032 {
33033 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
33034 {
33035 *width = FRAME_CURSOR_WIDTH (f);
33036 return FRAME_DESIRED_CURSOR (f);
33037 }
33038 else
33039 return get_specified_cursor_type (BVAR (b, cursor_type), width);
33040 }
33041
33042 *active_cursor = false;
33043 non_selected = true;
33044 }
33045
33046
33047 else if (w != XWINDOW (f->selected_window)
33048 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
33049 {
33050 *active_cursor = false;
33051
33052 if (MINI_WINDOW_P (w) &&
33053 (minibuf_level == 0
33054 || is_minibuffer (0, w->contents)))
33055 return NO_CURSOR;
33056
33057 non_selected = true;
33058 }
33059
33060
33061 if (NILP (BVAR (b, cursor_type)))
33062 return NO_CURSOR;
33063
33064
33065 if (EQ (BVAR (b, cursor_type), Qt))
33066 {
33067 cursor_type = FRAME_DESIRED_CURSOR (f);
33068 *width = FRAME_CURSOR_WIDTH (f);
33069 }
33070 else
33071 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
33072
33073
33074
33075 if (non_selected)
33076 {
33077 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
33078 if (!EQ (Qt, alt_cursor))
33079 return get_specified_cursor_type (alt_cursor, width);
33080
33081 if (cursor_type == FILLED_BOX_CURSOR)
33082 cursor_type = HOLLOW_BOX_CURSOR;
33083 else if (cursor_type == BAR_CURSOR && *width > 1)
33084 --*width;
33085 return cursor_type;
33086 }
33087
33088
33089 if (!w->cursor_off_p)
33090 {
33091 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
33092 return NO_CURSOR;
33093 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
33094 {
33095 if (cursor_type == FILLED_BOX_CURSOR)
33096 {
33097
33098
33099
33100
33101 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
33102 if (img != NULL && IMAGEP (img->spec))
33103 {
33104
33105
33106
33107
33108
33109
33110 if (!img->mask
33111 || (CONSP (BVAR (b, cursor_type))
33112 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33113 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33114 cursor_type = HOLLOW_BOX_CURSOR;
33115 }
33116 }
33117 else if (cursor_type != NO_CURSOR)
33118 {
33119
33120
33121
33122 cursor_type = HOLLOW_BOX_CURSOR;
33123 }
33124 }
33125 return cursor_type;
33126 }
33127
33128
33129
33130
33131 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33132 return get_specified_cursor_type (XCDR (alt_cursor), width);
33133
33134
33135 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33136 {
33137 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33138 return FRAME_BLINK_OFF_CURSOR (f);
33139 }
33140
33141 #if false
33142
33143
33144
33145
33146
33147
33148
33149
33150
33151
33152 if (cursor_type == FILLED_BOX_CURSOR)
33153 return HOLLOW_BOX_CURSOR;
33154
33155 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33156 {
33157 *width = 1;
33158 return cursor_type;
33159 }
33160 #endif
33161
33162 return NO_CURSOR;
33163 }
33164
33165
33166
33167
33168
33169
33170
33171
33172
33173 static void
33174 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33175 int x0, int x1, int y0, int y1)
33176 {
33177 int cx0, cx1, cy0, cy1;
33178 struct glyph_row *row;
33179
33180 if (!w->phys_cursor_on_p)
33181 return;
33182 if (area != TEXT_AREA)
33183 return;
33184
33185 if (w->phys_cursor.vpos < 0
33186 || w->phys_cursor.vpos >= w->current_matrix->nrows
33187 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33188 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33189 return;
33190
33191 if (row->cursor_in_fringe_p)
33192 {
33193 row->cursor_in_fringe_p = false;
33194 draw_fringe_bitmap (w, row, row->reversed_p);
33195 w->phys_cursor_on_p = false;
33196 return;
33197 }
33198
33199 cx0 = w->phys_cursor.x;
33200 cx1 = cx0 + w->phys_cursor_width;
33201 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33202 return;
33203
33204
33205
33206
33207
33208
33209
33210
33211
33212
33213
33214
33215
33216
33217
33218
33219
33220 cy0 = w->phys_cursor.y;
33221 cy1 = cy0 + w->phys_cursor_height;
33222 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33223 return;
33224
33225 w->phys_cursor_on_p = false;
33226 }
33227
33228 #endif
33229
33230
33231
33232
33233
33234
33235 #ifdef HAVE_WINDOW_SYSTEM
33236
33237
33238
33239
33240
33241 void
33242 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33243 enum glyph_row_area area, int overlaps)
33244 {
33245 int i, x;
33246
33247 block_input ();
33248
33249 x = 0;
33250 for (i = 0; i < row->used[area];)
33251 {
33252 if (row->glyphs[area][i].overlaps_vertically_p)
33253 {
33254 int start = i, start_x = x;
33255
33256 do
33257 {
33258 x += row->glyphs[area][i].pixel_width;
33259 ++i;
33260 }
33261 while (i < row->used[area]
33262 && row->glyphs[area][i].overlaps_vertically_p);
33263
33264 draw_glyphs (w, start_x, row, area,
33265 start, i,
33266 DRAW_NORMAL_TEXT, overlaps);
33267 }
33268 else
33269 {
33270 x += row->glyphs[area][i].pixel_width;
33271 ++i;
33272 }
33273 }
33274
33275 unblock_input ();
33276 }
33277
33278
33279
33280
33281
33282
33283 void
33284 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33285 enum draw_glyphs_face hl)
33286 {
33287
33288
33289
33290 if ((row->reversed_p
33291 ? (w->phys_cursor.hpos >= 0)
33292 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33293 {
33294 bool on_p = w->phys_cursor_on_p;
33295 int x1;
33296 int hpos = w->phys_cursor.hpos;
33297
33298
33299
33300
33301 if (!row->reversed_p && hpos < 0)
33302 hpos = 0;
33303 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33304 hpos = row->used[TEXT_AREA] - 1;
33305
33306 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33307 hl, 0);
33308 w->phys_cursor_on_p = on_p;
33309
33310 if (hl == DRAW_CURSOR)
33311 w->phys_cursor_width = x1 - w->phys_cursor.x;
33312
33313
33314
33315 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33316 {
33317 w->phys_cursor_width = x1 - w->phys_cursor.x;
33318
33319 if (row > w->current_matrix->rows
33320 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33321 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33322 OVERLAPS_ERASED_CURSOR);
33323
33324 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33325 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33326 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33327 OVERLAPS_ERASED_CURSOR);
33328 }
33329 }
33330 }
33331
33332
33333
33334
33335 void
33336 erase_phys_cursor (struct window *w)
33337 {
33338 struct frame *f = XFRAME (w->frame);
33339 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33340 int hpos = w->phys_cursor.hpos;
33341 int vpos = w->phys_cursor.vpos;
33342 bool mouse_face_here_p = false;
33343 struct glyph_matrix *active_glyphs = w->current_matrix;
33344 struct glyph_row *cursor_row;
33345 struct glyph *cursor_glyph;
33346 enum draw_glyphs_face hl;
33347
33348
33349
33350 if (w->phys_cursor_type == NO_CURSOR)
33351 goto mark_cursor_off;
33352
33353
33354
33355 if (vpos >= active_glyphs->nrows)
33356 goto mark_cursor_off;
33357
33358
33359
33360 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33361 if (!cursor_row->enabled_p)
33362 goto mark_cursor_off;
33363
33364
33365
33366 cursor_row->visible_height = min (cursor_row->visible_height,
33367 window_text_bottom_y (w) - cursor_row->y);
33368
33369
33370
33371
33372 if (cursor_row->visible_height <= 0)
33373 goto mark_cursor_off;
33374
33375
33376 if (cursor_row->cursor_in_fringe_p)
33377 {
33378 cursor_row->cursor_in_fringe_p = false;
33379 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33380 goto mark_cursor_off;
33381 }
33382
33383
33384
33385
33386
33387
33388 if ((cursor_row->reversed_p
33389 ? (w->phys_cursor.hpos < 0)
33390 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33391 goto mark_cursor_off;
33392
33393
33394
33395
33396 if (!cursor_row->reversed_p && hpos < 0)
33397 hpos = 0;
33398 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33399 hpos = cursor_row->used[TEXT_AREA] - 1;
33400
33401
33402
33403 if (! NILP (hlinfo->mouse_face_window)
33404 && coords_in_mouse_face_p (w, hpos, vpos)
33405
33406
33407
33408 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33409 mouse_face_here_p = true;
33410
33411 #ifdef HAVE_WINDOW_SYSTEM
33412
33413
33414
33415
33416 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33417 {
33418 w->phys_cursor_on_p = false;
33419 w->phys_cursor_type = NO_CURSOR;
33420 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33421 return;
33422 }
33423 #endif
33424
33425
33426 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33427 {
33428 int x, y;
33429 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33430 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33431 int width;
33432
33433 cursor_glyph = get_phys_cursor_glyph (w);
33434 if (cursor_glyph == NULL)
33435 goto mark_cursor_off;
33436
33437 width = cursor_glyph->pixel_width;
33438 x = w->phys_cursor.x;
33439 if (x < 0)
33440 {
33441 width += x;
33442 x = 0;
33443 }
33444 width = min (width, window_box_width (w, TEXT_AREA) - x);
33445 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33446 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33447
33448 if (width > 0)
33449 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33450 }
33451
33452
33453 if (mouse_face_here_p)
33454 hl = DRAW_MOUSE_FACE;
33455 else
33456 hl = DRAW_NORMAL_TEXT;
33457 draw_phys_cursor_glyph (w, cursor_row, hl);
33458
33459 mark_cursor_off:
33460 w->phys_cursor_on_p = false;
33461 w->phys_cursor_type = NO_CURSOR;
33462 }
33463
33464
33465
33466
33467
33468
33469 void
33470 display_and_set_cursor (struct window *w, bool on,
33471 int hpos, int vpos, int x, int y)
33472 {
33473 struct frame *f = XFRAME (w->frame);
33474 int new_cursor_type;
33475 int new_cursor_width UNINIT;
33476 bool active_cursor;
33477 struct glyph_row *glyph_row;
33478 struct glyph *glyph;
33479
33480
33481
33482
33483
33484 if (! FRAME_REDISPLAY_P (f)
33485 || vpos >= w->current_matrix->nrows
33486 || hpos >= w->current_matrix->matrix_w)
33487 return;
33488
33489
33490 if (!on && !w->phys_cursor_on_p)
33491 return;
33492
33493 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33494
33495
33496 if (!glyph_row->enabled_p)
33497 {
33498 w->phys_cursor_on_p = false;
33499 return;
33500 }
33501
33502
33503
33504
33505
33506
33507
33508
33509
33510 if (FRAME_GARBAGED_P (f))
33511 {
33512 if (on)
33513 {
33514 w->phys_cursor.x = x;
33515 w->phys_cursor.y = glyph_row->y;
33516 w->phys_cursor.hpos = hpos;
33517 w->phys_cursor.vpos = vpos;
33518 }
33519 return;
33520 }
33521
33522 glyph = NULL;
33523 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33524 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33525
33526 eassert (input_blocked_p ());
33527
33528
33529 new_cursor_type = get_window_cursor_type (w, glyph,
33530 &new_cursor_width, &active_cursor);
33531
33532
33533
33534
33535 if (w->phys_cursor_on_p
33536 && (!on
33537 || w->phys_cursor.x != x
33538 || w->phys_cursor.y != y
33539
33540
33541
33542 || hpos < 0
33543 || new_cursor_type != w->phys_cursor_type
33544 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33545 && new_cursor_width != w->phys_cursor_width)))
33546 erase_phys_cursor (w);
33547
33548
33549
33550
33551
33552
33553 if (on)
33554 {
33555 w->phys_cursor_ascent = glyph_row->ascent;
33556 w->phys_cursor_height = glyph_row->height;
33557
33558
33559
33560 w->phys_cursor.x = x;
33561 w->phys_cursor.y = glyph_row->y;
33562 w->phys_cursor.hpos = hpos;
33563 w->phys_cursor.vpos = vpos;
33564 }
33565
33566 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33567 new_cursor_type, new_cursor_width,
33568 on, active_cursor);
33569 }
33570
33571
33572
33573
33574
33575 static void
33576 update_window_cursor (struct window *w, bool on)
33577 {
33578
33579
33580 if (w->current_matrix)
33581 {
33582 int hpos = w->phys_cursor.hpos;
33583 int vpos = w->phys_cursor.vpos;
33584 struct glyph_row *row;
33585
33586 if (vpos >= w->current_matrix->nrows
33587 || hpos >= w->current_matrix->matrix_w)
33588 return;
33589
33590 row = MATRIX_ROW (w->current_matrix, vpos);
33591
33592
33593
33594
33595 if (!row->reversed_p && hpos < 0)
33596 hpos = 0;
33597 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33598 hpos = row->used[TEXT_AREA] - 1;
33599
33600 block_input ();
33601 display_and_set_cursor (w, on, hpos, vpos,
33602 w->phys_cursor.x, w->phys_cursor.y);
33603 unblock_input ();
33604 }
33605 }
33606
33607
33608
33609
33610
33611 static void
33612 update_cursor_in_window_tree (struct window *w, bool on_p)
33613 {
33614 while (w)
33615 {
33616 if (WINDOWP (w->contents))
33617 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33618 else
33619 update_window_cursor (w, on_p);
33620
33621 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33622 }
33623 }
33624
33625
33626
33627
33628
33629
33630 void
33631 gui_update_cursor (struct frame *f, bool on_p)
33632 {
33633 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33634 }
33635
33636
33637
33638
33639
33640
33641
33642 void
33643 gui_clear_cursor (struct window *w)
33644 {
33645 if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33646 update_window_cursor (w, false);
33647 }
33648
33649 #endif
33650
33651
33652
33653 static void
33654 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33655 int start_hpos, int end_hpos,
33656 enum draw_glyphs_face draw)
33657 {
33658 #ifdef HAVE_WINDOW_SYSTEM
33659 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33660 {
33661 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33662 return;
33663 }
33664 #endif
33665
33666 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33667 }
33668
33669
33670
33671 static void
33672 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33673 {
33674
33675
33676 if (!WINDOWP (hlinfo->mouse_face_window))
33677 return;
33678
33679 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33680 struct frame *f = XFRAME (WINDOW_FRAME (w));
33681
33682
33683 if (f != hlinfo->mouse_face_mouse_frame)
33684 return;
33685
33686 if (
33687
33688 w->current_matrix != NULL
33689
33690 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33691
33692
33693 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33694 {
33695 bool phys_cursor_on_p = w->phys_cursor_on_p;
33696 #ifdef HAVE_WINDOW_SYSTEM
33697 int mouse_off = 0;
33698 #endif
33699 struct glyph_row *row, *first, *last;
33700
33701 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33702 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33703
33704 for (row = first; row <= last && row->enabled_p; ++row)
33705 {
33706 int start_hpos, end_hpos, start_x;
33707
33708
33709 if (row == first)
33710 {
33711
33712
33713
33714
33715 if (!row->reversed_p)
33716 {
33717 start_hpos = hlinfo->mouse_face_beg_col;
33718 start_x = hlinfo->mouse_face_beg_x;
33719 }
33720 else if (row == last)
33721 {
33722 start_hpos = hlinfo->mouse_face_end_col;
33723 start_x = hlinfo->mouse_face_end_x;
33724 }
33725 else
33726 {
33727 start_hpos = 0;
33728 start_x = 0;
33729 }
33730 }
33731 else if (row->reversed_p && row == last)
33732 {
33733 start_hpos = hlinfo->mouse_face_end_col;
33734 start_x = hlinfo->mouse_face_end_x;
33735 }
33736 else
33737 {
33738 start_hpos = 0;
33739 start_x = 0;
33740 }
33741
33742 if (row == last)
33743 {
33744 if (!row->reversed_p)
33745 end_hpos = hlinfo->mouse_face_end_col;
33746 else if (row == first)
33747 end_hpos = hlinfo->mouse_face_beg_col;
33748 else
33749 {
33750 end_hpos = row->used[TEXT_AREA];
33751 if (draw == DRAW_NORMAL_TEXT)
33752 row->fill_line_p = true;
33753 }
33754 }
33755 else if (row->reversed_p && row == first)
33756 end_hpos = hlinfo->mouse_face_beg_col;
33757 else
33758 {
33759 end_hpos = row->used[TEXT_AREA];
33760 if (draw == DRAW_NORMAL_TEXT)
33761 row->fill_line_p = true;
33762 }
33763
33764 if (end_hpos > start_hpos)
33765 {
33766 draw_row_with_mouse_face (w, start_x, row,
33767 start_hpos, end_hpos, draw);
33768
33769 row->mouse_face_p
33770 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
33771 }
33772 #ifdef HAVE_WINDOW_SYSTEM
33773
33774 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
33775
33776
33777 && !w->pseudo_window_p
33778 && draw == DRAW_MOUSE_FACE)
33779 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
33780 #endif
33781 }
33782
33783
33784
33785 if (FRAME_WINDOW_P (f)
33786 && phys_cursor_on_p && !w->phys_cursor_on_p)
33787 {
33788 #ifdef HAVE_WINDOW_SYSTEM
33789 int hpos = w->phys_cursor.hpos;
33790 int old_phys_cursor_x = w->phys_cursor.x;
33791
33792
33793
33794
33795 if (!row->reversed_p && hpos < 0)
33796 hpos = 0;
33797 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33798 hpos = row->used[TEXT_AREA] - 1;
33799
33800 block_input ();
33801 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
33802 w->phys_cursor.x + mouse_off,
33803 w->phys_cursor.y);
33804
33805
33806 w->phys_cursor.x = old_phys_cursor_x;
33807 unblock_input ();
33808 #endif
33809 }
33810 }
33811
33812 #ifdef HAVE_WINDOW_SYSTEM
33813
33814 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
33815 {
33816 if (draw == DRAW_NORMAL_TEXT
33817 #ifndef HAVE_EXT_TOOL_BAR
33818 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
33819 #endif
33820 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
33821 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
33822 else
33823 if (draw == DRAW_MOUSE_FACE)
33824 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
33825 else
33826 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
33827 }
33828 #endif
33829 }
33830
33831
33832
33833
33834
33835
33836 bool
33837 clear_mouse_face (Mouse_HLInfo *hlinfo)
33838 {
33839 bool cleared
33840 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
33841 if (cleared)
33842 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
33843 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
33844 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
33845 hlinfo->mouse_face_window = Qnil;
33846 hlinfo->mouse_face_overlay = Qnil;
33847 return cleared;
33848 }
33849
33850
33851
33852 static bool
33853 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
33854 {
33855 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
33856
33857
33858 if (!(WINDOWP (hlinfo->mouse_face_window)
33859 && XWINDOW (hlinfo->mouse_face_window) == w))
33860 return false;
33861 if (vpos < hlinfo->mouse_face_beg_row
33862 || vpos > hlinfo->mouse_face_end_row)
33863 return false;
33864 if (vpos > hlinfo->mouse_face_beg_row
33865 && vpos < hlinfo->mouse_face_end_row)
33866 return true;
33867
33868 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
33869 {
33870 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
33871 {
33872 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
33873 return true;
33874 }
33875 else if ((vpos == hlinfo->mouse_face_beg_row
33876 && hpos >= hlinfo->mouse_face_beg_col)
33877 || (vpos == hlinfo->mouse_face_end_row
33878 && hpos < hlinfo->mouse_face_end_col))
33879 return true;
33880 }
33881 else
33882 {
33883 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
33884 {
33885 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
33886 return true;
33887 }
33888 else if ((vpos == hlinfo->mouse_face_beg_row
33889 && hpos <= hlinfo->mouse_face_beg_col)
33890 || (vpos == hlinfo->mouse_face_end_row
33891 && hpos > hlinfo->mouse_face_end_col))
33892 return true;
33893 }
33894 return false;
33895 }
33896
33897
33898
33899
33900
33901 bool
33902 cursor_in_mouse_face_p (struct window *w)
33903 {
33904 int vpos = w->phys_cursor.vpos;
33905
33906
33907
33908 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
33909 return false;
33910
33911 int hpos = w->phys_cursor.hpos;
33912 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
33913
33914
33915
33916
33917 if (!row->reversed_p && hpos < 0)
33918 hpos = 0;
33919 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33920 hpos = row->used[TEXT_AREA] - 1;
33921
33922 return coords_in_mouse_face_p (w, hpos, vpos);
33923 }
33924
33925
33926
33927
33928
33929
33930
33931
33932
33933 static void
33934 rows_from_pos_range (struct window *w,
33935 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
33936 Lisp_Object disp_string,
33937 struct glyph_row **start, struct glyph_row **end)
33938 {
33939 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
33940 int last_y = window_text_bottom_y (w);
33941 struct glyph_row *row;
33942
33943 *start = NULL;
33944 *end = NULL;
33945
33946 while (!first->enabled_p
33947 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
33948 first++;
33949
33950
33951 for (row = first;
33952 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
33953 row++)
33954 {
33955
33956
33957
33958 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
33959 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
33960
33961
33962
33963
33964 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
33965 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
33966 && !row->ends_at_zv_p
33967 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
33968 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
33969 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
33970 && !row->ends_at_zv_p
33971 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
33972 {
33973
33974
33975
33976
33977
33978
33979
33980
33981
33982
33983 struct glyph *g = row->glyphs[TEXT_AREA];
33984 struct glyph *e = g + row->used[TEXT_AREA];
33985
33986 while (g < e)
33987 {
33988 if (((BUFFERP (g->object) || NILP (g->object))
33989 && start_charpos <= g->charpos && g->charpos < end_charpos)
33990
33991
33992 || EQ (g->object, disp_string))
33993 *start = row;
33994 g++;
33995 }
33996 if (*start)
33997 break;
33998 }
33999 }
34000
34001
34002 if (!*start
34003
34004
34005 && !(row->enabled_p
34006 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
34007 row = first;
34008 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
34009 {
34010 struct glyph_row *next = row + 1;
34011 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
34012
34013 if (!next->enabled_p
34014 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
34015
34016
34017
34018 || (start_charpos < next_start
34019 && end_charpos < next_start)
34020 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
34021 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
34022 && !next->ends_at_zv_p
34023 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
34024 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
34025 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
34026 && !next->ends_at_zv_p
34027 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
34028 {
34029 *end = row;
34030 break;
34031 }
34032 else
34033 {
34034
34035
34036
34037 struct glyph *g = next->glyphs[TEXT_AREA];
34038 struct glyph *s = g;
34039 struct glyph *e = g + next->used[TEXT_AREA];
34040
34041 while (g < e)
34042 {
34043 if (((BUFFERP (g->object) || NILP (g->object))
34044 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
34045
34046
34047
34048
34049
34050 || (((!next->reversed_p && g == s)
34051 || (next->reversed_p && g == e - 1))
34052 && (g->charpos == end_charpos
34053
34054
34055 || (g->charpos == -1
34056 && !row->ends_at_zv_p
34057 && next_start == end_charpos)))))
34058
34059
34060 || EQ (g->object, disp_string))
34061 break;
34062 g++;
34063 }
34064 if (g == e)
34065 {
34066 *end = row;
34067 break;
34068 }
34069
34070
34071 else if (next->ends_at_zv_p)
34072 {
34073 *end = next;
34074 break;
34075 }
34076 }
34077 }
34078 }
34079
34080
34081
34082
34083
34084
34085
34086
34087
34088
34089 static void
34090 mouse_face_from_buffer_pos (Lisp_Object window,
34091 Mouse_HLInfo *hlinfo,
34092 ptrdiff_t mouse_charpos,
34093 ptrdiff_t start_charpos,
34094 ptrdiff_t end_charpos,
34095 Lisp_Object before_string,
34096 Lisp_Object after_string,
34097 Lisp_Object disp_string)
34098 {
34099 struct window *w = XWINDOW (window);
34100 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34101 struct glyph_row *r1, *r2;
34102 struct glyph *glyph, *end;
34103 ptrdiff_t ignore, pos;
34104 int x;
34105
34106 eassert (NILP (disp_string) || STRINGP (disp_string));
34107 eassert (NILP (before_string) || STRINGP (before_string));
34108 eassert (NILP (after_string) || STRINGP (after_string));
34109
34110
34111 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
34112 if (r1 == NULL)
34113 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34114
34115
34116 if (!NILP (before_string) || !NILP (disp_string))
34117 {
34118 struct glyph_row *prev;
34119 while ((prev = r1 - 1, prev >= first)
34120 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34121 && prev->used[TEXT_AREA] > 0)
34122 {
34123 struct glyph *beg = prev->glyphs[TEXT_AREA];
34124 glyph = beg + prev->used[TEXT_AREA];
34125 while (--glyph >= beg && NILP (glyph->object));
34126 if (glyph < beg
34127 || !(EQ (glyph->object, before_string)
34128 || EQ (glyph->object, disp_string)))
34129 break;
34130 r1 = prev;
34131 }
34132 }
34133 if (r2 == NULL)
34134 {
34135 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34136 hlinfo->mouse_face_past_end = true;
34137 }
34138 else if (!NILP (after_string))
34139 {
34140
34141 struct glyph_row *next;
34142 struct glyph_row *last
34143 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34144
34145 for (next = r2 + 1;
34146 next <= last
34147 && next->used[TEXT_AREA] > 0
34148 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34149 ++next)
34150 r2 = next;
34151 }
34152
34153
34154
34155
34156
34157 if (r1->y > r2->y)
34158 {
34159 struct glyph_row *tem = r2;
34160
34161 r2 = r1;
34162 r1 = tem;
34163 }
34164
34165 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34166 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34167
34168
34169
34170
34171
34172
34173
34174
34175
34176
34177
34178 if (!r1->reversed_p)
34179 {
34180
34181
34182 glyph = r1->glyphs[TEXT_AREA];
34183 end = glyph + r1->used[TEXT_AREA];
34184 x = r1->x;
34185
34186
34187 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34188 for (; glyph < end
34189 && NILP (glyph->object)
34190 && glyph->charpos < 0;
34191 ++glyph)
34192 x += glyph->pixel_width;
34193
34194
34195
34196
34197 for (; glyph < end
34198 && !NILP (glyph->object)
34199 && !EQ (glyph->object, disp_string)
34200 && !(BUFFERP (glyph->object)
34201 && (glyph->charpos >= start_charpos
34202 && glyph->charpos < end_charpos));
34203 ++glyph)
34204 {
34205
34206
34207
34208 if (EQ (glyph->object, before_string))
34209 {
34210 pos = string_buffer_position (before_string,
34211 start_charpos);
34212
34213
34214 if (!pos || (pos >= start_charpos && pos < end_charpos))
34215 break;
34216 }
34217 else if (EQ (glyph->object, after_string))
34218 {
34219 pos = string_buffer_position (after_string, end_charpos);
34220 if (!pos || (pos >= start_charpos && pos < end_charpos))
34221 break;
34222 }
34223 x += glyph->pixel_width;
34224 }
34225 hlinfo->mouse_face_beg_x = x;
34226 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34227 }
34228 else
34229 {
34230
34231
34232 struct glyph *g;
34233
34234 end = r1->glyphs[TEXT_AREA] - 1;
34235 glyph = end + r1->used[TEXT_AREA];
34236
34237
34238 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34239 for (; glyph > end
34240 && NILP (glyph->object)
34241 && glyph->charpos < 0;
34242 --glyph)
34243 ;
34244
34245
34246
34247
34248 for (; glyph > end
34249 && !NILP (glyph->object)
34250 && !EQ (glyph->object, disp_string)
34251 && !(BUFFERP (glyph->object)
34252 && (glyph->charpos >= start_charpos
34253 && glyph->charpos < end_charpos));
34254 --glyph)
34255 {
34256
34257
34258
34259 if (EQ (glyph->object, before_string))
34260 {
34261 pos = string_buffer_position (before_string, start_charpos);
34262
34263
34264 if (!pos || (pos >= start_charpos && pos < end_charpos))
34265 break;
34266 }
34267 else if (EQ (glyph->object, after_string))
34268 {
34269 pos = string_buffer_position (after_string, end_charpos);
34270 if (!pos || (pos >= start_charpos && pos < end_charpos))
34271 break;
34272 }
34273 }
34274
34275 glyph++;
34276 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34277 x += g->pixel_width;
34278 hlinfo->mouse_face_beg_x = x;
34279 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34280 }
34281
34282
34283
34284
34285 if (r2 != r1)
34286 {
34287 if (!r2->reversed_p)
34288 {
34289 glyph = r2->glyphs[TEXT_AREA];
34290 end = glyph + r2->used[TEXT_AREA];
34291 x = r2->x;
34292 }
34293 else
34294 {
34295 end = r2->glyphs[TEXT_AREA] - 1;
34296 glyph = end + r2->used[TEXT_AREA];
34297 }
34298 }
34299
34300 if (!r2->reversed_p)
34301 {
34302
34303
34304
34305 while (end > glyph
34306 && NILP ((end - 1)->object))
34307 --end;
34308
34309
34310
34311
34312 for (--end;
34313 end > glyph
34314 && !NILP (end->object)
34315 && !EQ (end->object, disp_string)
34316 && !(BUFFERP (end->object)
34317 && (end->charpos >= start_charpos
34318 && end->charpos < end_charpos));
34319 --end)
34320 {
34321
34322
34323
34324 if (EQ (end->object, before_string))
34325 {
34326 pos = string_buffer_position (before_string, start_charpos);
34327 if (!pos || (pos >= start_charpos && pos < end_charpos))
34328 break;
34329 }
34330 else if (EQ (end->object, after_string))
34331 {
34332 pos = string_buffer_position (after_string, end_charpos);
34333 if (!pos || (pos >= start_charpos && pos < end_charpos))
34334 break;
34335 }
34336 }
34337
34338 for (; glyph <= end; ++glyph)
34339 x += glyph->pixel_width;
34340
34341 hlinfo->mouse_face_end_x = x;
34342 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34343 }
34344 else
34345 {
34346
34347
34348
34349 x = r2->x;
34350 end++;
34351 while (end < glyph
34352 && NILP (end->object))
34353 {
34354 x += end->pixel_width;
34355 ++end;
34356 }
34357
34358
34359
34360
34361 for ( ;
34362 end < glyph
34363 && !NILP (end->object)
34364 && !EQ (end->object, disp_string)
34365 && !(BUFFERP (end->object)
34366 && (end->charpos >= start_charpos
34367 && end->charpos < end_charpos));
34368 ++end)
34369 {
34370
34371
34372
34373 if (EQ (end->object, before_string))
34374 {
34375 pos = string_buffer_position (before_string, start_charpos);
34376 if (!pos || (pos >= start_charpos && pos < end_charpos))
34377 break;
34378 }
34379 else if (EQ (end->object, after_string))
34380 {
34381 pos = string_buffer_position (after_string, end_charpos);
34382 if (!pos || (pos >= start_charpos && pos < end_charpos))
34383 break;
34384 }
34385 x += end->pixel_width;
34386 }
34387
34388
34389
34390
34391
34392 if (end == glyph
34393 && BUFFERP (end->object)
34394 && (end->charpos < start_charpos
34395 || end->charpos >= end_charpos))
34396 {
34397 x += end->pixel_width;
34398 ++end;
34399 }
34400 hlinfo->mouse_face_end_x = x;
34401 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34402 }
34403
34404 hlinfo->mouse_face_window = window;
34405 hlinfo->mouse_face_face_id
34406 = face_at_buffer_position (w, mouse_charpos, &ignore,
34407 mouse_charpos + 1,
34408 !hlinfo->mouse_face_hidden, -1, 0);
34409 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34410 }
34411
34412
34413
34414
34415
34416 #if false
34417
34418
34419
34420
34421
34422
34423
34424
34425
34426
34427
34428
34429
34430
34431
34432
34433 static bool
34434 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34435 int *hpos, int *vpos, int *x, int *y, bool right_p)
34436 {
34437 int yb = window_text_bottom_y (w);
34438 struct glyph_row *r;
34439 struct glyph *best_glyph = NULL;
34440 struct glyph_row *best_row = NULL;
34441 int best_x = 0;
34442
34443 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34444 r->enabled_p && r->y < yb;
34445 ++r)
34446 {
34447 struct glyph *g = r->glyphs[TEXT_AREA];
34448 struct glyph *e = g + r->used[TEXT_AREA];
34449 int gx;
34450
34451 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34452 if (EQ (g->object, object))
34453 {
34454 if (g->charpos == pos)
34455 {
34456 best_glyph = g;
34457 best_x = gx;
34458 best_row = r;
34459 goto found;
34460 }
34461 else if (best_glyph == NULL
34462 || ((eabs (g->charpos - pos)
34463 < eabs (best_glyph->charpos - pos))
34464 && (right_p
34465 ? g->charpos < pos
34466 : g->charpos > pos)))
34467 {
34468 best_glyph = g;
34469 best_x = gx;
34470 best_row = r;
34471 }
34472 }
34473 }
34474
34475 found:
34476
34477 if (best_glyph)
34478 {
34479 *x = best_x;
34480 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34481
34482 if (right_p)
34483 {
34484 *x += best_glyph->pixel_width;
34485 ++*hpos;
34486 }
34487
34488 *y = best_row->y;
34489 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34490 }
34491
34492 return best_glyph != NULL;
34493 }
34494 #endif
34495
34496
34497
34498
34499
34500
34501 static void
34502 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34503 Lisp_Object object,
34504 ptrdiff_t startpos, ptrdiff_t endpos)
34505 {
34506 int yb = window_text_bottom_y (w);
34507 struct glyph_row *r;
34508 struct glyph *g, *e;
34509 int gx;
34510 bool found = false;
34511
34512
34513
34514
34515 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34516 r->enabled_p && r->y < yb;
34517 ++r)
34518 {
34519 if (!r->reversed_p)
34520 {
34521 g = r->glyphs[TEXT_AREA];
34522 e = g + r->used[TEXT_AREA];
34523 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34524 if (EQ (g->object, object)
34525 && startpos <= g->charpos && g->charpos < endpos)
34526 {
34527 hlinfo->mouse_face_beg_row
34528 = MATRIX_ROW_VPOS (r, w->current_matrix);
34529 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34530 hlinfo->mouse_face_beg_x = gx;
34531 found = true;
34532 break;
34533 }
34534 }
34535 else
34536 {
34537 struct glyph *g1;
34538
34539 e = r->glyphs[TEXT_AREA];
34540 g = e + r->used[TEXT_AREA];
34541 for ( ; g > e; --g)
34542 if (EQ ((g-1)->object, object)
34543 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34544 {
34545 hlinfo->mouse_face_beg_row
34546 = MATRIX_ROW_VPOS (r, w->current_matrix);
34547 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34548 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34549 gx += g1->pixel_width;
34550 hlinfo->mouse_face_beg_x = gx;
34551 found = true;
34552 break;
34553 }
34554 }
34555 if (found)
34556 break;
34557 }
34558
34559 if (!found)
34560 return;
34561
34562
34563
34564 for (++r; r->enabled_p && r->y < yb; ++r)
34565 {
34566 g = r->glyphs[TEXT_AREA];
34567 e = g + r->used[TEXT_AREA];
34568 found = false;
34569 for ( ; g < e; ++g)
34570 if (EQ (g->object, object)
34571 && startpos <= g->charpos && g->charpos < endpos)
34572 {
34573 found = true;
34574 break;
34575 }
34576 if (!found)
34577 break;
34578 }
34579
34580
34581 r--;
34582
34583
34584 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34585
34586
34587
34588 if (!r->reversed_p)
34589 {
34590 g = r->glyphs[TEXT_AREA];
34591 e = g + r->used[TEXT_AREA];
34592 for ( ; e > g; --e)
34593 if (EQ ((e-1)->object, object)
34594 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34595 break;
34596 hlinfo->mouse_face_end_col = e - g;
34597
34598 for (gx = r->x; g < e; ++g)
34599 gx += g->pixel_width;
34600 hlinfo->mouse_face_end_x = gx;
34601 }
34602 else
34603 {
34604 e = r->glyphs[TEXT_AREA];
34605 g = e + r->used[TEXT_AREA];
34606 for (gx = r->x ; e < g; ++e)
34607 {
34608 if (EQ (e->object, object)
34609 && startpos <= e->charpos && e->charpos < endpos)
34610 break;
34611 gx += e->pixel_width;
34612 }
34613 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34614 hlinfo->mouse_face_end_x = gx;
34615 }
34616 }
34617
34618 #ifdef HAVE_WINDOW_SYSTEM
34619
34620
34621
34622 static bool
34623 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34624 {
34625 if (!CONSP (hot_spot))
34626 return false;
34627
34628 if (EQ (XCAR (hot_spot), Qrect))
34629 {
34630
34631 Lisp_Object rect = XCDR (hot_spot);
34632 Lisp_Object tem;
34633 if (!CONSP (rect))
34634 return false;
34635 if (!CONSP (XCAR (rect)))
34636 return false;
34637 if (!CONSP (XCDR (rect)))
34638 return false;
34639 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34640 return false;
34641 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34642 return false;
34643 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34644 return false;
34645 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34646 return false;
34647 return true;
34648 }
34649 else if (EQ (XCAR (hot_spot), Qcircle))
34650 {
34651
34652 Lisp_Object circ = XCDR (hot_spot);
34653 Lisp_Object lr, lx0, ly0;
34654 if (CONSP (circ)
34655 && CONSP (XCAR (circ))
34656 && (lr = XCDR (circ), NUMBERP (lr))
34657 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34658 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34659 {
34660 double r = XFLOATINT (lr);
34661 double dx = XFIXNUM (lx0) - x;
34662 double dy = XFIXNUM (ly0) - y;
34663 return (dx * dx + dy * dy <= r * r);
34664 }
34665 }
34666 else if (EQ (XCAR (hot_spot), Qpoly))
34667 {
34668
34669 if (VECTORP (XCDR (hot_spot)))
34670 {
34671 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34672 Lisp_Object *poly = v->contents;
34673 ptrdiff_t n = v->header.size;
34674 ptrdiff_t i;
34675 bool inside = false;
34676 Lisp_Object lx, ly;
34677 int x0, y0;
34678
34679
34680 if (n < 6 || n & 1)
34681 return false;
34682
34683
34684
34685
34686
34687 if ((lx = poly[n-2], !FIXNUMP (lx))
34688 || (ly = poly[n-1], !FIXNUMP (lx)))
34689 return false;
34690 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34691 for (i = 0; i < n; i += 2)
34692 {
34693 int x1 = x0, y1 = y0;
34694 if ((lx = poly[i], !FIXNUMP (lx))
34695 || (ly = poly[i+1], !FIXNUMP (ly)))
34696 return false;
34697 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34698
34699
34700 if (x0 >= x)
34701 {
34702 if (x1 >= x)
34703 continue;
34704 }
34705 else if (x1 < x)
34706 continue;
34707 if (y > y0 && y > y1)
34708 continue;
34709 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34710 inside = !inside;
34711 }
34712 return inside;
34713 }
34714 }
34715 return false;
34716 }
34717
34718 Lisp_Object
34719 find_hot_spot (Lisp_Object map, int x, int y)
34720 {
34721 while (CONSP (map))
34722 {
34723 if (CONSP (XCAR (map))
34724 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34725 return XCAR (map);
34726 map = XCDR (map);
34727 }
34728
34729 return Qnil;
34730 }
34731
34732 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34733 3, 3, 0,
34734 doc:
34735
34736
34737
34738
34739
34740
34741
34742
34743 )
34744 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
34745 {
34746 if (NILP (map))
34747 return Qnil;
34748
34749 CHECK_FIXNUM (x);
34750 CHECK_FIXNUM (y);
34751
34752 return find_hot_spot (map,
34753 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
34754 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
34755 }
34756 #endif
34757
34758
34759
34760 static void
34761 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
34762 {
34763 #ifdef HAVE_WINDOW_SYSTEM
34764 if (!FRAME_WINDOW_P (f))
34765 return;
34766
34767
34768 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
34769 || EQ (track_mouse, Qdrag_source))
34770 return;
34771
34772 if (!NILP (pointer))
34773 {
34774 if (EQ (pointer, Qarrow))
34775 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34776 else if (EQ (pointer, Qhand))
34777 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34778 else if (EQ (pointer, Qtext))
34779 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
34780 else if (EQ (pointer, intern ("hdrag")))
34781 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
34782 else if (EQ (pointer, intern ("nhdrag")))
34783 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34784 # ifdef HAVE_X_WINDOWS
34785 else if (EQ (pointer, intern ("vdrag")))
34786 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
34787 # endif
34788 else if (EQ (pointer, intern ("hourglass")))
34789 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
34790 else if (EQ (pointer, Qmodeline))
34791 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
34792 else
34793 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34794 }
34795
34796 if (cursor != No_Cursor)
34797 FRAME_RIF (f)->define_frame_cursor (f, cursor);
34798 #endif
34799 }
34800
34801
34802
34803
34804
34805
34806
34807 static void
34808 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
34809 enum window_part area)
34810 {
34811 struct window *w = XWINDOW (window);
34812 struct frame *f = XFRAME (w->frame);
34813 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
34814 Emacs_Cursor cursor = No_Cursor;
34815 Lisp_Object pointer = Qnil;
34816 int dx, dy, width, height;
34817 ptrdiff_t charpos;
34818 Lisp_Object string, object = Qnil;
34819 Lisp_Object pos UNINIT;
34820 Lisp_Object mouse_face;
34821 int original_x_pixel = x;
34822 struct glyph * glyph = NULL, * row_start_glyph = NULL;
34823 struct glyph_row *row UNINIT;
34824
34825 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
34826 {
34827 int x0;
34828 struct glyph *end;
34829
34830
34831
34832 string = mode_line_string (w, area, &x, &y, &charpos,
34833 &object, &dx, &dy, &width, &height);
34834
34835 row = (area == ON_MODE_LINE
34836 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
34837 : (area == ON_TAB_LINE
34838 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
34839 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
34840
34841
34842 if (row->mode_line_p && row->enabled_p)
34843 {
34844 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
34845 end = glyph + row->used[TEXT_AREA];
34846
34847 for (x0 = original_x_pixel;
34848 glyph < end && x0 >= glyph->pixel_width;
34849 ++glyph)
34850 x0 -= glyph->pixel_width;
34851
34852 if (glyph >= end)
34853 glyph = NULL;
34854 }
34855 }
34856 else
34857 {
34858 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
34859
34860
34861 string = marginal_area_string (w, area, &x, &y, &charpos,
34862 &object, &dx, &dy, &width, &height);
34863 }
34864
34865 Lisp_Object help = Qnil;
34866
34867 #ifdef HAVE_WINDOW_SYSTEM
34868 if (IMAGEP (object))
34869 {
34870 Lisp_Object image_map, hotspot;
34871 if ((image_map = plist_get (XCDR (object), QCmap),
34872 !NILP (image_map))
34873 && (hotspot = find_hot_spot (image_map, dx, dy),
34874 CONSP (hotspot))
34875 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
34876 {
34877 Lisp_Object plist;
34878
34879
34880
34881
34882 hotspot = XCDR (hotspot);
34883 if (CONSP (hotspot)
34884 && (plist = XCAR (hotspot), CONSP (plist)))
34885 {
34886 pointer = plist_get (plist, Qpointer);
34887 if (NILP (pointer))
34888 pointer = Qhand;
34889 help = plist_get (plist, Qhelp_echo);
34890 if (!NILP (help))
34891 {
34892 help_echo_string = help;
34893 XSETWINDOW (help_echo_window, w);
34894 help_echo_object = w->contents;
34895 help_echo_pos = charpos;
34896 }
34897 }
34898 }
34899 if (NILP (pointer))
34900 pointer = plist_get (XCDR (object), QCpointer);
34901 }
34902 #endif
34903
34904
34905
34906
34907 if (STRINGP (string))
34908 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
34909
34910
34911
34912
34913
34914 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
34915 || area == ON_TAB_LINE)
34916 {
34917
34918
34919 if (NILP (help))
34920 {
34921 if (STRINGP (string))
34922 help = Fget_text_property (pos, Qhelp_echo, string);
34923
34924 if (!NILP (help))
34925 {
34926 help_echo_string = help;
34927 XSETWINDOW (help_echo_window, w);
34928 help_echo_object = string;
34929 help_echo_pos = charpos;
34930 }
34931 else if (area == ON_MODE_LINE
34932 && !NILP (w->mode_line_help_echo))
34933 {
34934 help_echo_string = w->mode_line_help_echo;
34935 XSETWINDOW (help_echo_window, w);
34936 help_echo_object = Qnil;
34937 help_echo_pos = -1;
34938 }
34939 }
34940
34941 #ifdef HAVE_WINDOW_SYSTEM
34942
34943 if (FRAME_WINDOW_P (f))
34944 {
34945 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
34946 || minibuf_level
34947 || NILP (Vresize_mini_windows));
34948
34949 if (STRINGP (string))
34950 {
34951 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34952
34953 if (NILP (pointer))
34954 pointer = Fget_text_property (pos, Qpointer, string);
34955
34956
34957 if (NILP (pointer)
34958 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
34959 || area == ON_TAB_LINE))
34960 {
34961 Lisp_Object map;
34962
34963 map = Fget_text_property (pos, Qlocal_map, string);
34964 if (!KEYMAPP (map))
34965 map = Fget_text_property (pos, Qkeymap, string);
34966 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
34967 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34968 }
34969 }
34970 else if (draggable && area == ON_MODE_LINE)
34971 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34972 else if ((area == ON_MODE_LINE
34973 && WINDOW_BOTTOMMOST_P (w)
34974 && !FRAME_HAS_MINIBUF_P (f)
34975 && !NILP (Fframe_parameter
34976 (w->frame, Qdrag_with_mode_line)))
34977 || (((area == ON_HEADER_LINE
34978 && !NILP (Fframe_parameter
34979 (w->frame, Qdrag_with_header_line)))
34980 || (area == ON_TAB_LINE
34981 && !NILP (Fframe_parameter
34982 (w->frame, Qdrag_with_tab_line))))
34983 && WINDOW_TOPMOST_P (w)))
34984 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34985 else
34986 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34987 }
34988 #endif
34989 }
34990
34991
34992 bool mouse_face_shown = false;
34993
34994 if (STRINGP (string))
34995 {
34996 mouse_face = Fget_text_property (pos, Qmouse_face, string);
34997 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
34998 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
34999 || (area == ON_TAB_LINE))
35000 && glyph)
35001 {
35002 Lisp_Object b, e;
35003
35004 struct glyph * tmp_glyph;
35005
35006 int gpos;
35007 int gseq_length;
35008 int total_pixel_width;
35009 ptrdiff_t begpos, endpos, ignore;
35010
35011 int vpos, hpos;
35012
35013 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
35014 Qmouse_face, string, Qnil);
35015 if (NILP (b))
35016 begpos = 0;
35017 else
35018 begpos = XFIXNUM (b);
35019
35020 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
35021 if (NILP (e))
35022 endpos = SCHARS (string);
35023 else
35024 endpos = XFIXNUM (e);
35025
35026
35027
35028
35029
35030
35031
35032
35033
35034
35035
35036 tmp_glyph = row_start_glyph;
35037 while (tmp_glyph < glyph
35038 && (!(EQ (tmp_glyph->object, glyph->object)
35039 && begpos <= tmp_glyph->charpos
35040 && tmp_glyph->charpos < endpos)))
35041 tmp_glyph++;
35042 gpos = glyph - tmp_glyph;
35043
35044
35045
35046
35047
35048
35049 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
35050 tmp_glyph > glyph
35051 && (!(EQ (tmp_glyph->object, glyph->object)
35052 && begpos <= tmp_glyph->charpos
35053 && tmp_glyph->charpos < endpos));
35054 tmp_glyph--)
35055 ;
35056 gseq_length = gpos + (tmp_glyph - glyph) + 1;
35057
35058
35059
35060 total_pixel_width = 0;
35061 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
35062 total_pixel_width += tmp_glyph->pixel_width;
35063
35064
35065
35066
35067 hpos = x - gpos;
35068 vpos = (area == ON_MODE_LINE
35069 ? (w->current_matrix)->nrows - 1
35070 : (area == ON_TAB_LINE
35071 ? 0
35072 : (w->current_matrix->tab_line_p
35073 ? 1
35074 : 0)));
35075
35076
35077
35078 if ( EQ (window, hlinfo->mouse_face_window)
35079 && (!row->reversed_p
35080 ? (hlinfo->mouse_face_beg_col <= hpos
35081 && hpos < hlinfo->mouse_face_end_col)
35082
35083 : (hlinfo->mouse_face_end_col <= hpos
35084 && hpos < hlinfo->mouse_face_beg_col))
35085 && hlinfo->mouse_face_beg_row == vpos )
35086 return;
35087
35088 if (clear_mouse_face (hlinfo))
35089 cursor = No_Cursor;
35090
35091 if (!row->reversed_p)
35092 {
35093 hlinfo->mouse_face_beg_col = hpos;
35094 hlinfo->mouse_face_beg_x = original_x_pixel
35095 - (total_pixel_width + dx);
35096 hlinfo->mouse_face_end_col = hpos + gseq_length;
35097 hlinfo->mouse_face_end_x = 0;
35098 }
35099 else
35100 {
35101
35102
35103 hlinfo->mouse_face_end_col = hpos;
35104 hlinfo->mouse_face_end_x = original_x_pixel
35105 - (total_pixel_width + dx);
35106 hlinfo->mouse_face_beg_col = hpos + gseq_length;
35107 hlinfo->mouse_face_beg_x = 0;
35108 }
35109
35110 hlinfo->mouse_face_beg_row = vpos;
35111 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
35112 hlinfo->mouse_face_past_end = false;
35113 hlinfo->mouse_face_window = window;
35114
35115 hlinfo->mouse_face_face_id =
35116 face_at_string_position (w, string, charpos, 0, &ignore,
35117 glyph->face_id, true, 0);
35118
35119 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35120 mouse_face_shown = true;
35121
35122 if (NILP (pointer))
35123 pointer = Qhand;
35124 }
35125 }
35126
35127
35128
35129 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35130 || area == ON_TAB_LINE) && !mouse_face_shown)
35131 clear_mouse_face (hlinfo);
35132
35133 define_frame_cursor1 (f, cursor, pointer);
35134 }
35135
35136
35137
35138
35139
35140
35141
35142
35143
35144
35145 void
35146 note_mouse_highlight (struct frame *f, int x, int y)
35147 {
35148 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35149 enum window_part part = ON_NOTHING;
35150 Lisp_Object window;
35151 struct window *w;
35152 Emacs_Cursor cursor = No_Cursor;
35153 Lisp_Object pointer = Qnil;
35154 struct buffer *b;
35155
35156
35157 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS)
35158 if (popup_activated ())
35159 return;
35160 #endif
35161
35162 #if defined (HAVE_HAIKU)
35163 if (popup_activated_p)
35164 return;
35165 #endif
35166
35167 if (!f->glyphs_initialized_p
35168 || f->pointer_invisible)
35169 return;
35170
35171 hlinfo->mouse_face_mouse_x = x;
35172 hlinfo->mouse_face_mouse_y = y;
35173 hlinfo->mouse_face_mouse_frame = f;
35174
35175 if (hlinfo->mouse_face_defer)
35176 return;
35177
35178
35179 window = window_from_coordinates (f, x, y, &part, true, true);
35180
35181
35182 if (! EQ (window, hlinfo->mouse_face_window)
35183
35184 || (!NILP (hlinfo->mouse_face_window)
35185 && !NILP (window)
35186 && part != ON_TEXT
35187 && part != ON_MODE_LINE
35188 && part != ON_HEADER_LINE
35189 && part != ON_TAB_LINE))
35190 clear_mouse_face (hlinfo);
35191
35192
35193 help_echo_string = Qnil;
35194
35195
35196 if (!FRAME_WINDOW_P (f)
35197 && (y >= FRAME_MENU_BAR_LINES (f)
35198 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35199 {
35200 int prop_idx;
35201 bool ignore;
35202 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35203
35204 if (!NILP (caption))
35205 {
35206 help_echo_object = help_echo_window = Qnil;
35207 help_echo_pos = -1;
35208 help_echo_string = AREF (f->tab_bar_items,
35209 prop_idx * TAB_BAR_ITEM_NSLOTS
35210 + TAB_BAR_ITEM_HELP);
35211 if (NILP (help_echo_string))
35212 help_echo_string = caption;
35213 }
35214 }
35215
35216 #ifdef HAVE_WINDOW_SYSTEM
35217
35218
35219 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35220 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35221 {
35222 enum internal_border_part part = frame_internal_border_part (f, x, y);
35223
35224 switch (part)
35225 {
35226 case INTERNAL_BORDER_NONE:
35227 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35228
35229 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35230 break;
35231 case INTERNAL_BORDER_LEFT_EDGE:
35232 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35233 break;
35234 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35235 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35236 break;
35237 case INTERNAL_BORDER_TOP_EDGE:
35238 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35239 break;
35240 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35241 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35242 break;
35243 case INTERNAL_BORDER_RIGHT_EDGE:
35244 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35245 break;
35246 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35247 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35248 break;
35249 case INTERNAL_BORDER_BOTTOM_EDGE:
35250 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35251 break;
35252 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35253 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35254 break;
35255 default:
35256
35257 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35258 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35259 }
35260
35261 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35262 {
35263
35264 help_echo_string = build_string ("drag-mouse-1: resize frame");
35265 goto set_cursor;
35266 }
35267 }
35268 #endif
35269
35270
35271 if (!WINDOWP (window))
35272 return;
35273
35274
35275 w = XWINDOW (window);
35276 frame_to_window_pixel_xy (w, &x, &y);
35277
35278 #if defined (HAVE_WINDOW_SYSTEM)
35279
35280
35281 if (EQ (window, f->tab_bar_window))
35282 {
35283 note_tab_bar_highlight (f, x, y);
35284 if (tab_bar__dragging_in_progress)
35285 {
35286 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35287 goto set_cursor;
35288 }
35289 else
35290 return;
35291 }
35292 else
35293 {
35294
35295
35296
35297
35298 f->last_tab_bar_item = -1;
35299 }
35300 #endif
35301
35302 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35303
35304
35305 if (EQ (window, f->tool_bar_window))
35306 {
35307 note_tool_bar_highlight (f, x, y);
35308 return;
35309 }
35310 #endif
35311
35312
35313 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35314 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35315 {
35316 note_mode_line_or_margin_highlight (window, x, y, part);
35317
35318 #ifdef HAVE_WINDOW_SYSTEM
35319 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35320 {
35321 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35322
35323 goto set_cursor;
35324 }
35325 else
35326 #endif
35327 return;
35328 }
35329
35330 #ifdef HAVE_WINDOW_SYSTEM
35331 if (part == ON_VERTICAL_BORDER)
35332 {
35333 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35334 help_echo_string = build_string ("drag-mouse-1: resize");
35335 goto set_cursor;
35336 }
35337 else if (part == ON_RIGHT_DIVIDER)
35338 {
35339 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35340 help_echo_string = build_string ("drag-mouse-1: resize");
35341 goto set_cursor;
35342 }
35343 else if (part == ON_BOTTOM_DIVIDER)
35344 if (! WINDOW_BOTTOMMOST_P (w)
35345 || minibuf_level
35346 || NILP (Vresize_mini_windows))
35347 {
35348 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35349 help_echo_string = build_string ("drag-mouse-1: resize");
35350 goto set_cursor;
35351 }
35352 else
35353 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35354 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35355 || part == ON_VERTICAL_SCROLL_BAR
35356 || part == ON_HORIZONTAL_SCROLL_BAR)
35357 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35358 else
35359 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35360 #endif
35361
35362
35363
35364 b = XBUFFER (w->contents);
35365 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35366 {
35367 int hpos, vpos, dx, dy, area = LAST_AREA;
35368 ptrdiff_t pos;
35369 struct glyph *glyph;
35370 Lisp_Object object;
35371 Lisp_Object mouse_face = Qnil, position;
35372 Lisp_Object *overlay_vec = NULL;
35373 ptrdiff_t i, noverlays;
35374 struct buffer *obuf;
35375 ptrdiff_t obegv, ozv;
35376 bool same_region;
35377
35378
35379 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35380
35381 #ifdef HAVE_WINDOW_SYSTEM
35382
35383 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35384 {
35385 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35386 if (img != NULL && IMAGEP (img->spec))
35387 {
35388 Lisp_Object image_map, hotspot;
35389 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35390 !NILP (image_map))
35391 && (hotspot = find_hot_spot (image_map,
35392 glyph->slice.img.x + dx,
35393 glyph->slice.img.y + dy),
35394 CONSP (hotspot))
35395 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35396 {
35397 Lisp_Object plist;
35398
35399
35400
35401
35402
35403 hotspot = XCDR (hotspot);
35404 if (CONSP (hotspot)
35405 && (plist = XCAR (hotspot), CONSP (plist)))
35406 {
35407 pointer = plist_get (plist, Qpointer);
35408 if (NILP (pointer))
35409 pointer = Qhand;
35410 help_echo_string = plist_get (plist, Qhelp_echo);
35411 if (!NILP (help_echo_string))
35412 {
35413 help_echo_window = window;
35414 help_echo_object = glyph->object;
35415 help_echo_pos = glyph->charpos;
35416 }
35417 }
35418 }
35419 if (NILP (pointer))
35420 pointer = plist_get (XCDR (img->spec), QCpointer);
35421 }
35422 }
35423 #endif
35424
35425
35426 if (glyph == NULL
35427 || area != TEXT_AREA
35428 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35429
35430
35431
35432
35433
35434 || NILP (glyph->object)
35435
35436
35437
35438
35439 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35440 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35441 && glyph->type == STRETCH_GLYPH
35442 && glyph->avoid_cursor_p))
35443 {
35444 if (clear_mouse_face (hlinfo))
35445 cursor = No_Cursor;
35446 if (FRAME_WINDOW_P (f) && NILP (pointer))
35447 {
35448 #ifdef HAVE_WINDOW_SYSTEM
35449 if (area != TEXT_AREA)
35450 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35451 else
35452 pointer = Vvoid_text_area_pointer;
35453 #endif
35454 }
35455 goto set_cursor;
35456 }
35457
35458 pos = glyph->charpos;
35459 object = glyph->object;
35460 if (!STRINGP (object) && !BUFFERP (object))
35461 goto set_cursor;
35462
35463
35464 if (BUFFERP (object) && pos > BUF_Z (b))
35465 goto set_cursor;
35466
35467
35468
35469 obuf = current_buffer;
35470 current_buffer = b;
35471 obegv = BEGV;
35472 ozv = ZV;
35473 BEGV = BEG;
35474 ZV = Z;
35475
35476
35477 position = make_fixnum (pos);
35478
35479 USE_SAFE_ALLOCA;
35480
35481 if (BUFFERP (object))
35482 {
35483
35484 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35485
35486 noverlays = sort_overlays (overlay_vec, noverlays, w);
35487 }
35488 else
35489 noverlays = 0;
35490
35491 if (NILP (Vmouse_highlight))
35492 {
35493 clear_mouse_face (hlinfo);
35494 goto check_help_echo;
35495 }
35496
35497 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35498
35499 if (same_region)
35500 cursor = No_Cursor;
35501
35502
35503 if (! same_region
35504
35505
35506
35507
35508
35509 || (!hlinfo->mouse_face_hidden
35510 && OVERLAYP (hlinfo->mouse_face_overlay)
35511
35512 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35513 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35514 {
35515
35516 Lisp_Object overlay = Qnil;
35517 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35518 {
35519 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35520 if (!NILP (mouse_face))
35521 overlay = overlay_vec[i];
35522 }
35523
35524
35525
35526 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35527 goto check_help_echo;
35528
35529
35530 if (clear_mouse_face (hlinfo))
35531 cursor = No_Cursor;
35532
35533
35534 hlinfo->mouse_face_overlay = overlay;
35535
35536
35537 if (NILP (overlay))
35538 mouse_face = Fget_text_property (position, Qmouse_face, object);
35539
35540
35541
35542 if (!NILP (mouse_face) && STRINGP (object))
35543 {
35544
35545
35546 Lisp_Object s, e;
35547 ptrdiff_t ignore;
35548
35549 s = Fprevious_single_property_change
35550 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35551 e = Fnext_single_property_change
35552 (position, Qmouse_face, object, Qnil);
35553 if (NILP (s))
35554 s = make_fixnum (0);
35555 if (NILP (e))
35556 e = make_fixnum (SCHARS (object));
35557 mouse_face_from_string_pos (w, hlinfo, object,
35558 XFIXNUM (s), XFIXNUM (e));
35559 hlinfo->mouse_face_past_end = false;
35560 hlinfo->mouse_face_window = window;
35561 hlinfo->mouse_face_face_id
35562 = face_at_string_position (w, object, pos, 0, &ignore,
35563 glyph->face_id, true, 0);
35564 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35565 cursor = No_Cursor;
35566 }
35567 else
35568 {
35569
35570
35571 Lisp_Object buffer UNINIT;
35572 Lisp_Object disp_string UNINIT;
35573
35574 if (STRINGP (object))
35575 {
35576
35577
35578 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35579 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35580 pos = string_buffer_position (object, start);
35581 if (pos > 0)
35582 {
35583 mouse_face = get_char_property_and_overlay
35584 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35585 buffer = w->contents;
35586 disp_string = object;
35587 }
35588 }
35589 else
35590 {
35591 buffer = object;
35592 disp_string = Qnil;
35593 }
35594
35595 if (!NILP (mouse_face))
35596 {
35597 Lisp_Object before, after;
35598 Lisp_Object before_string, after_string;
35599
35600
35601
35602
35603
35604
35605
35606
35607
35608
35609 Lisp_Object lim1
35610 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35611 ? Fmarker_position (w->start)
35612 : Qnil;
35613 Lisp_Object lim2
35614 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35615 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35616 - w->window_end_pos)
35617 : Qnil;
35618
35619 if (NILP (overlay))
35620 {
35621
35622 before = Fprevious_single_property_change
35623 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35624 after = Fnext_single_property_change
35625 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35626 before_string = after_string = Qnil;
35627 }
35628 else
35629 {
35630
35631 before = Foverlay_start (overlay);
35632 after = Foverlay_end (overlay);
35633 before_string = Foverlay_get (overlay, Qbefore_string);
35634 after_string = Foverlay_get (overlay, Qafter_string);
35635
35636 if (!STRINGP (before_string)) before_string = Qnil;
35637 if (!STRINGP (after_string)) after_string = Qnil;
35638 }
35639
35640 mouse_face_from_buffer_pos (window, hlinfo, pos,
35641 NILP (before)
35642 ? 1
35643 : XFIXNAT (before),
35644 NILP (after)
35645 ? BUF_Z (XBUFFER (buffer))
35646 : XFIXNAT (after),
35647 before_string, after_string,
35648 disp_string);
35649 cursor = No_Cursor;
35650 }
35651 }
35652 }
35653
35654 check_help_echo:
35655
35656
35657 if (NILP (help_echo_string)) {
35658 Lisp_Object help, overlay;
35659
35660
35661 help = overlay = Qnil;
35662 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35663 {
35664 overlay = overlay_vec[i];
35665 help = Foverlay_get (overlay, Qhelp_echo);
35666 }
35667
35668 if (!NILP (help))
35669 {
35670 help_echo_string = help;
35671 help_echo_window = window;
35672 help_echo_object = overlay;
35673 help_echo_pos = pos;
35674 }
35675 else
35676 {
35677 Lisp_Object obj = glyph->object;
35678 ptrdiff_t charpos = glyph->charpos;
35679
35680
35681 if (STRINGP (obj)
35682 && charpos >= 0
35683 && charpos < SCHARS (obj))
35684 {
35685 help = Fget_text_property (make_fixnum (charpos),
35686 Qhelp_echo, obj);
35687 if (NILP (help))
35688 {
35689
35690
35691 struct glyph_row *r
35692 = MATRIX_ROW (w->current_matrix, vpos);
35693 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35694 ptrdiff_t p = string_buffer_position (obj, start);
35695 if (p > 0)
35696 {
35697 help = Fget_char_property (make_fixnum (p),
35698 Qhelp_echo, w->contents);
35699 if (!NILP (help))
35700 {
35701 charpos = p;
35702 obj = w->contents;
35703 }
35704 }
35705 }
35706 }
35707 else if (BUFFERP (obj)
35708 && charpos >= BEGV
35709 && charpos < ZV)
35710 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35711 obj);
35712
35713 if (!NILP (help))
35714 {
35715 help_echo_string = help;
35716 help_echo_window = window;
35717 help_echo_object = obj;
35718 help_echo_pos = charpos;
35719 }
35720 }
35721 }
35722
35723 #ifdef HAVE_WINDOW_SYSTEM
35724
35725 if (FRAME_WINDOW_P (f) && NILP (pointer))
35726 {
35727
35728 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35729 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35730
35731 if (NILP (pointer))
35732 {
35733 Lisp_Object obj = glyph->object;
35734 ptrdiff_t charpos = glyph->charpos;
35735
35736
35737 if (STRINGP (obj)
35738 && charpos >= 0
35739 && charpos < SCHARS (obj))
35740 {
35741 pointer = Fget_text_property (make_fixnum (charpos),
35742 Qpointer, obj);
35743 if (NILP (pointer))
35744 {
35745
35746
35747 struct glyph_row *r
35748 = MATRIX_ROW (w->current_matrix, vpos);
35749 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35750 ptrdiff_t p = string_buffer_position (obj, start);
35751 if (p > 0)
35752 pointer = Fget_char_property (make_fixnum (p),
35753 Qpointer, w->contents);
35754 }
35755 }
35756 else if (BUFFERP (obj)
35757 && charpos >= BEGV
35758 && charpos < ZV)
35759 pointer = Fget_text_property (make_fixnum (charpos),
35760 Qpointer, obj);
35761 }
35762 }
35763 #endif
35764
35765 BEGV = obegv;
35766 ZV = ozv;
35767 current_buffer = obuf;
35768 SAFE_FREE ();
35769 }
35770
35771 set_cursor:
35772 define_frame_cursor1 (f, cursor, pointer);
35773 }
35774
35775
35776
35777
35778
35779
35780
35781 void
35782 gui_clear_window_mouse_face (struct window *w)
35783 {
35784 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
35785 Lisp_Object window;
35786
35787 block_input ();
35788 XSETWINDOW (window, w);
35789 if (EQ (window, hlinfo->mouse_face_window))
35790 clear_mouse_face (hlinfo);
35791 unblock_input ();
35792 }
35793
35794
35795
35796
35797
35798
35799 void
35800 cancel_mouse_face (struct frame *f)
35801 {
35802 Lisp_Object window;
35803 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35804
35805 window = hlinfo->mouse_face_window;
35806 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
35807 reset_mouse_highlight (hlinfo);
35808 }
35809
35810
35811
35812
35813
35814
35815
35816 #ifdef HAVE_WINDOW_SYSTEM
35817
35818
35819
35820
35821 static void
35822 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
35823 enum glyph_row_area area)
35824 {
35825 struct glyph *first = row->glyphs[area];
35826 struct glyph *end = row->glyphs[area] + row->used[area];
35827 struct glyph *last;
35828 int first_x, start_x, x;
35829
35830 if (area == TEXT_AREA && row->fill_line_p)
35831
35832 draw_glyphs (w, row->x, row, area,
35833 0, row->used[area],
35834 DRAW_NORMAL_TEXT, 0);
35835 else
35836 {
35837
35838
35839
35840 start_x = window_box_left_offset (w, area);
35841 x = start_x;
35842 if (area == TEXT_AREA)
35843 x += row->x;
35844
35845
35846 while (first < end
35847 && x + first->pixel_width < r->x)
35848 {
35849 x += first->pixel_width;
35850 ++first;
35851 }
35852
35853
35854 last = first;
35855 first_x = x;
35856
35857
35858
35859 int r_end = r->x + r->width;
35860 while (last < end && x < r_end)
35861 {
35862 x += last->pixel_width;
35863 ++last;
35864 }
35865
35866
35867 if (last > first)
35868 draw_glyphs (w, first_x - start_x, row, area,
35869 first - row->glyphs[area], last - row->glyphs[area],
35870 DRAW_NORMAL_TEXT, 0);
35871 }
35872 }
35873
35874
35875
35876
35877
35878
35879 static bool
35880 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
35881 {
35882 eassert (row->enabled_p);
35883
35884 if (row->mode_line_p || w->pseudo_window_p)
35885 draw_glyphs (w, 0, row, TEXT_AREA,
35886 0, row->used[TEXT_AREA],
35887 DRAW_NORMAL_TEXT, 0);
35888 else
35889 {
35890 if (row->used[LEFT_MARGIN_AREA])
35891 expose_area (w, row, r, LEFT_MARGIN_AREA);
35892 if (row->used[TEXT_AREA])
35893 expose_area (w, row, r, TEXT_AREA);
35894 if (row->used[RIGHT_MARGIN_AREA])
35895 expose_area (w, row, r, RIGHT_MARGIN_AREA);
35896 draw_row_fringe_bitmaps (w, row);
35897 }
35898
35899 return row->mouse_face_p;
35900 }
35901
35902
35903
35904
35905
35906
35907
35908
35909
35910
35911 static void
35912 expose_overlaps (struct window *w,
35913 struct glyph_row *first_overlapping_row,
35914 struct glyph_row *last_overlapping_row,
35915 const Emacs_Rectangle *r)
35916 {
35917 struct glyph_row *row;
35918
35919 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
35920 if (row->overlapping_p)
35921 {
35922 eassert (row->enabled_p && !row->mode_line_p);
35923
35924 row->clip = r;
35925 if (row->used[LEFT_MARGIN_AREA])
35926 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
35927
35928 if (row->used[TEXT_AREA])
35929 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
35930
35931 if (row->used[RIGHT_MARGIN_AREA])
35932 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
35933 row->clip = NULL;
35934 }
35935 }
35936
35937
35938
35939
35940 static bool
35941 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
35942 {
35943 Emacs_Rectangle cr, result;
35944 struct glyph *cursor_glyph;
35945 struct glyph_row *row;
35946
35947 if (w->phys_cursor.vpos >= 0
35948 && w->phys_cursor.vpos < w->current_matrix->nrows
35949 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
35950 row->enabled_p)
35951 && row->cursor_in_fringe_p)
35952 {
35953
35954 cr.x = window_box_right_offset (w,
35955 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
35956 ? RIGHT_MARGIN_AREA
35957 : TEXT_AREA));
35958 cr.y = row->y;
35959 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
35960 cr.height = row->height;
35961 return gui_intersect_rectangles (&cr, r, &result);
35962 }
35963
35964 cursor_glyph = get_phys_cursor_glyph (w);
35965 if (cursor_glyph)
35966 {
35967
35968
35969 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
35970 cr.y = w->phys_cursor.y;
35971 cr.width = cursor_glyph->pixel_width;
35972 cr.height = w->phys_cursor_height;
35973
35974
35975 return gui_intersect_rectangles (&cr, r, &result);
35976 }
35977
35978 return false;
35979 }
35980
35981
35982
35983
35984
35985
35986 void
35987 gui_draw_vertical_border (struct window *w)
35988 {
35989 struct frame *f = XFRAME (WINDOW_FRAME (w));
35990
35991
35992
35993
35994
35995
35996
35997
35998
35999 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
36000 return;
36001
36002
36003
36004
36005 if (!WINDOW_RIGHTMOST_P (w)
36006 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
36007 {
36008 int x0, x1, y0, y1;
36009
36010 window_box_edges (w, &x0, &y0, &x1, &y1);
36011 y1 -= 1;
36012
36013 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36014 x1 -= 1;
36015
36016 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
36017 }
36018
36019 if (!WINDOW_LEFTMOST_P (w)
36020 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
36021 {
36022 int x0, x1, y0, y1;
36023
36024 window_box_edges (w, &x0, &y0, &x1, &y1);
36025 y1 -= 1;
36026
36027 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36028 x0 -= 1;
36029
36030 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
36031 }
36032 }
36033
36034
36035
36036
36037 void
36038 gui_draw_right_divider (struct window *w)
36039 {
36040 struct frame *f = WINDOW_XFRAME (w);
36041
36042 if (w->mini || w->pseudo_window_p)
36043 return;
36044 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36045 {
36046 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
36047 int x1 = WINDOW_RIGHT_EDGE_X (w);
36048 int y0 = WINDOW_TOP_EDGE_Y (w);
36049 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36050
36051
36052
36053 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
36054 && !NILP (w->parent)
36055 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
36056 && !NILP (w->next))
36057 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36058
36059 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36060 }
36061 }
36062
36063 static void
36064 gui_draw_bottom_divider (struct window *w)
36065 {
36066 struct frame *f = XFRAME (WINDOW_FRAME (w));
36067
36068 if (w->mini || w->pseudo_window_p)
36069 return;
36070 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36071 {
36072 int x0 = WINDOW_LEFT_EDGE_X (w);
36073 int x1 = WINDOW_RIGHT_EDGE_X (w);
36074 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36075 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36076 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
36077
36078
36079
36080 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
36081 && p
36082 && ((WINDOW_VERTICAL_COMBINATION_P (p)
36083 && !NILP (w->next))
36084 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
36085 && NILP (w->next)
36086 && !NILP (p->parent)
36087 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
36088 && !NILP (XWINDOW (p->parent)->next))))
36089 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
36090
36091 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36092 }
36093 }
36094
36095
36096
36097
36098
36099
36100 static bool
36101 expose_window (struct window *w, const Emacs_Rectangle *fr)
36102 {
36103 struct frame *f = XFRAME (w->frame);
36104 Emacs_Rectangle wr, r;
36105 bool mouse_face_overwritten_p = false;
36106
36107
36108
36109
36110
36111 if (w->current_matrix == NULL)
36112 return false;
36113
36114
36115
36116
36117 if (w->must_be_updated_p)
36118 {
36119 SET_FRAME_GARBAGED (f);
36120 return false;
36121 }
36122
36123
36124 wr.x = WINDOW_LEFT_EDGE_X (w);
36125 wr.y = WINDOW_TOP_EDGE_Y (w);
36126 wr.width = WINDOW_PIXEL_WIDTH (w);
36127 wr.height = WINDOW_PIXEL_HEIGHT (w);
36128
36129 if (gui_intersect_rectangles (fr, &wr, &r))
36130 {
36131 int yb = window_text_bottom_y (w);
36132 struct glyph_row *row;
36133 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36134
36135 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36136 r.x, r.y, r.width, r.height);
36137
36138
36139 r.x -= WINDOW_LEFT_EDGE_X (w);
36140 r.y -= WINDOW_TOP_EDGE_Y (w);
36141
36142
36143 bool cursor_cleared_p = (!w->pseudo_window_p
36144 && phys_cursor_in_rect_p (w, &r));
36145 if (cursor_cleared_p)
36146 gui_clear_cursor (w);
36147
36148
36149
36150
36151
36152
36153 bool phys_cursor_on_p = w->phys_cursor_on_p;
36154
36155
36156
36157
36158 int r_bottom = r.y + r.height;
36159
36160
36161
36162
36163
36164 bool buffer_changed = false;
36165 struct buffer *oldbuf = current_buffer;
36166 if (!w->pseudo_window_p)
36167 {
36168 set_buffer_internal_1 (XBUFFER (w->contents));
36169 buffer_changed = true;
36170 }
36171
36172
36173 first_overlapping_row = last_overlapping_row = NULL;
36174 for (row = w->current_matrix->rows;
36175 row->enabled_p;
36176 ++row)
36177 {
36178 int y0 = row->y;
36179 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36180
36181 if ((y0 >= r.y && y0 < r_bottom)
36182 || (y1 > r.y && y1 < r_bottom)
36183 || (r.y >= y0 && r.y < y1)
36184 || (r_bottom > y0 && r_bottom < y1))
36185 {
36186
36187
36188 if (row->overlapping_p && !row->mode_line_p)
36189 {
36190 if (first_overlapping_row == NULL)
36191 first_overlapping_row = row;
36192 last_overlapping_row = row;
36193 }
36194
36195 row->clip = fr;
36196 if (expose_line (w, row, &r))
36197 mouse_face_overwritten_p = true;
36198 row->clip = NULL;
36199 }
36200 else if (row->overlapping_p)
36201 {
36202
36203 if (y0 < r.y
36204 ? y0 + row->phys_height > r.y
36205 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36206 {
36207 if (first_overlapping_row == NULL)
36208 first_overlapping_row = row;
36209 last_overlapping_row = row;
36210 }
36211 }
36212
36213 if (y1 >= yb)
36214 break;
36215 }
36216
36217 if (buffer_changed)
36218 set_buffer_internal_1 (oldbuf);
36219
36220
36221 if (window_wants_mode_line (w)
36222 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36223 row->enabled_p)
36224 && row->y < r_bottom)
36225 {
36226 if (expose_line (w, row, &r))
36227 mouse_face_overwritten_p = true;
36228 }
36229
36230 if (!w->pseudo_window_p)
36231 {
36232
36233 if (first_overlapping_row)
36234 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36235 fr);
36236
36237
36238 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36239 gui_draw_right_divider (w);
36240 else
36241 gui_draw_vertical_border (w);
36242
36243 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36244 gui_draw_bottom_divider (w);
36245
36246
36247 if (cursor_cleared_p
36248 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36249 update_window_cursor (w, true);
36250 }
36251 }
36252
36253 return mouse_face_overwritten_p;
36254 }
36255
36256
36257
36258
36259
36260
36261
36262 static bool
36263 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36264 {
36265 struct frame *f = XFRAME (w->frame);
36266 bool mouse_face_overwritten_p = false;
36267
36268 while (w && !FRAME_GARBAGED_P (f))
36269 {
36270 mouse_face_overwritten_p
36271 |= (WINDOWP (w->contents)
36272 ? expose_window_tree (XWINDOW (w->contents), r)
36273 : expose_window (w, r));
36274
36275 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36276 }
36277
36278 return mouse_face_overwritten_p;
36279 }
36280
36281
36282
36283
36284
36285
36286
36287
36288 void
36289 expose_frame (struct frame *f, int x, int y, int w, int h)
36290 {
36291 Emacs_Rectangle r;
36292 bool mouse_face_overwritten_p = false;
36293
36294 if (FRAME_GARBAGED_P (f))
36295 {
36296 redisplay_trace ("expose_frame garbaged\n");
36297 return;
36298 }
36299
36300
36301
36302
36303 if (FRAME_FACE_CACHE (f) == NULL
36304 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36305 {
36306 redisplay_trace ("expose_frame no faces\n");
36307 return;
36308 }
36309
36310 if (w == 0 || h == 0)
36311 {
36312 r.x = r.y = 0;
36313 r.width = FRAME_TEXT_WIDTH (f);
36314 r.height = FRAME_TEXT_HEIGHT (f);
36315 }
36316 else
36317 {
36318 r.x = x;
36319 r.y = y;
36320 r.width = w;
36321 r.height = h;
36322 }
36323
36324 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36325 r.x, r.y, r.width, r.height);
36326 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36327
36328 if (WINDOWP (f->tab_bar_window))
36329 mouse_face_overwritten_p
36330 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36331
36332 #ifndef HAVE_EXT_TOOL_BAR
36333 if (WINDOWP (f->tool_bar_window))
36334 mouse_face_overwritten_p
36335 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36336 #endif
36337
36338 #ifdef HAVE_X_WINDOWS
36339 #ifndef MSDOS
36340 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
36341 if (WINDOWP (f->menu_bar_window))
36342 mouse_face_overwritten_p
36343 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36344 #endif
36345 #endif
36346 #endif
36347
36348
36349
36350
36351
36352
36353
36354
36355
36356
36357
36358
36359
36360
36361 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36362 {
36363 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36364 if (f == hlinfo->mouse_face_mouse_frame)
36365 {
36366 int mouse_x = hlinfo->mouse_face_mouse_x;
36367 int mouse_y = hlinfo->mouse_face_mouse_y;
36368 clear_mouse_face (hlinfo);
36369 note_mouse_highlight (f, mouse_x, mouse_y);
36370 }
36371 }
36372 }
36373
36374
36375
36376
36377
36378
36379
36380 bool
36381 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36382 Emacs_Rectangle *result)
36383 {
36384 const Emacs_Rectangle *left, *right;
36385 const Emacs_Rectangle *upper, *lower;
36386 bool intersection_p = false;
36387
36388
36389 if (r1->x < r2->x)
36390 left = r1, right = r2;
36391 else
36392 left = r2, right = r1;
36393
36394
36395
36396 if (right->x <= left->x + left->width)
36397 {
36398 result->x = right->x;
36399
36400
36401
36402 result->width = (min (left->x + left->width, right->x + right->width)
36403 - result->x);
36404
36405
36406 if (r1->y < r2->y)
36407 upper = r1, lower = r2;
36408 else
36409 upper = r2, lower = r1;
36410
36411
36412
36413 if (lower->y <= upper->y + upper->height)
36414 {
36415 result->y = lower->y;
36416
36417
36418
36419 result->height = (min (lower->y + lower->height,
36420 upper->y + upper->height)
36421 - result->y);
36422 intersection_p = true;
36423 }
36424 }
36425
36426 return intersection_p;
36427 }
36428
36429 #endif
36430
36431
36432
36433
36434
36435
36436 void
36437 syms_of_xdisp (void)
36438 {
36439 Vwith_echo_area_save_vector = Qnil;
36440 staticpro (&Vwith_echo_area_save_vector);
36441
36442 Vmessage_stack = Qnil;
36443 staticpro (&Vmessage_stack);
36444
36445
36446 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36447
36448 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36449
36450 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36451 scroll_minibuffer_conservatively,
36452 doc:
36453
36454 );
36455 scroll_minibuffer_conservatively = true;
36456
36457 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36458 doc:
36459
36460
36461
36462
36463
36464 );
36465 inhibit_message = false;
36466
36467 message_dolog_marker1 = Fmake_marker ();
36468 staticpro (&message_dolog_marker1);
36469 message_dolog_marker2 = Fmake_marker ();
36470 staticpro (&message_dolog_marker2);
36471 message_dolog_marker3 = Fmake_marker ();
36472 staticpro (&message_dolog_marker3);
36473
36474 defsubr (&Sset_buffer_redisplay);
36475 #ifdef GLYPH_DEBUG
36476 defsubr (&Sdump_frame_glyph_matrix);
36477 defsubr (&Sdump_glyph_matrix);
36478 defsubr (&Sdump_glyph_row);
36479 defsubr (&Sdump_tab_bar_row);
36480 defsubr (&Sdump_tool_bar_row);
36481 defsubr (&Strace_redisplay);
36482 defsubr (&Strace_to_stderr);
36483 #endif
36484 #ifdef HAVE_WINDOW_SYSTEM
36485 defsubr (&Stab_bar_height);
36486 defsubr (&Stool_bar_height);
36487 defsubr (&Slookup_image_map);
36488 #endif
36489 defsubr (&Sline_pixel_height);
36490 defsubr (&Sformat_mode_line);
36491 defsubr (&Sinvisible_p);
36492 defsubr (&Scurrent_bidi_paragraph_direction);
36493 defsubr (&Swindow_text_pixel_size);
36494 defsubr (&Sbuffer_text_pixel_size);
36495 defsubr (&Smove_point_visually);
36496 defsubr (&Sbidi_find_overridden_directionality);
36497 defsubr (&Sdisplay__line_is_continued_p);
36498 defsubr (&Sget_display_property);
36499 defsubr (&Slong_line_optimizations_p);
36500
36501 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36502 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36503 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36504 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36505 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36506 DEFSYM (Qeval, "eval");
36507 DEFSYM (QCdata, ":data");
36508
36509
36510 DEFSYM (Qdisplay, "display");
36511 DEFSYM (Qspace_width, "space-width");
36512 DEFSYM (Qraise, "raise");
36513 DEFSYM (Qslice, "slice");
36514 DEFSYM (Qspace, "space");
36515 DEFSYM (Qmargin, "margin");
36516 DEFSYM (Qpointer, "pointer");
36517 DEFSYM (Qleft_margin, "left-margin");
36518 DEFSYM (Qright_margin, "right-margin");
36519 DEFSYM (Qcenter, "center");
36520 DEFSYM (Qline_height, "line-height");
36521 DEFSYM (QCalign_to, ":align-to");
36522 DEFSYM (QCrelative_width, ":relative-width");
36523 DEFSYM (QCrelative_height, ":relative-height");
36524 DEFSYM (QCeval, ":eval");
36525 DEFSYM (QCpropertize, ":propertize");
36526 DEFSYM (QCfile, ":file");
36527 DEFSYM (Qfontified, "fontified");
36528 DEFSYM (Qfontification_functions, "fontification-functions");
36529 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36530 "long-line-optimizations-in-fontification-functions");
36531
36532
36533
36534 DEFSYM (Qdisable_eval, "disable-eval");
36535
36536
36537 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36538
36539
36540 DEFSYM (Qline_number, "line-number");
36541 DEFSYM (Qline_number_current_line, "line-number-current-line");
36542 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36543 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36544
36545 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36546
36547
36548 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36549
36550
36551 DEFSYM (Qescape_glyph, "escape-glyph");
36552
36553
36554
36555 DEFSYM (Qnobreak_space, "nobreak-space");
36556 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36557
36558
36559
36560 DEFSYM (Qimage, "image");
36561
36562
36563 DEFSYM (Qtext, "text");
36564 DEFSYM (Qboth, "both");
36565 DEFSYM (Qboth_horiz, "both-horiz");
36566 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36567
36568
36569 DEFSYM (QCmap, ":map");
36570 DEFSYM (QCpointer, ":pointer");
36571 DEFSYM (Qrect, "rect");
36572 DEFSYM (Qcircle, "circle");
36573 DEFSYM (Qpoly, "poly");
36574
36575 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36576
36577 DEFSYM (Qgrow_only, "grow-only");
36578 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36579 DEFSYM (Qposition, "position");
36580 DEFSYM (Qbuffer_position, "buffer-position");
36581 DEFSYM (Qobject, "object");
36582
36583
36584 DEFSYM (Qbar, "bar");
36585 DEFSYM (Qhbar, "hbar");
36586 DEFSYM (Qbox, "box");
36587 DEFSYM (Qhollow, "hollow");
36588
36589
36590 DEFSYM (Qhand, "hand");
36591 DEFSYM (Qarrow, "arrow");
36592
36593
36594 DEFSYM (Qdragging, "dragging");
36595 DEFSYM (Qdropping, "dropping");
36596 DEFSYM (Qdrag_source, "drag-source");
36597
36598 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36599 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36600 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36601
36602 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36603
36604 list_of_error = list1 (Qerror);
36605 staticpro (&list_of_error);
36606
36607
36608
36609
36610
36611 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36612 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36613
36614
36615
36616 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36617 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36618
36619 echo_buffer[0] = echo_buffer[1] = Qnil;
36620 staticpro (&echo_buffer[0]);
36621 staticpro (&echo_buffer[1]);
36622
36623 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36624 staticpro (&echo_area_buffer[0]);
36625 staticpro (&echo_area_buffer[1]);
36626
36627 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36628 doc:
36629
36630
36631
36632 );
36633 Vmessages_buffer_name = build_string ("*Messages*");
36634
36635 mode_line_proptrans_alist = Qnil;
36636 staticpro (&mode_line_proptrans_alist);
36637 mode_line_string_list = Qnil;
36638 staticpro (&mode_line_string_list);
36639 mode_line_string_face = Qnil;
36640 staticpro (&mode_line_string_face);
36641 mode_line_string_face_prop = Qnil;
36642 staticpro (&mode_line_string_face_prop);
36643 Vmode_line_unwind_vector = Qnil;
36644 staticpro (&Vmode_line_unwind_vector);
36645
36646 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36647
36648 help_echo_string = Qnil;
36649 staticpro (&help_echo_string);
36650 help_echo_object = Qnil;
36651 staticpro (&help_echo_object);
36652 help_echo_window = Qnil;
36653 staticpro (&help_echo_window);
36654 previous_help_echo_string = Qnil;
36655 staticpro (&previous_help_echo_string);
36656 help_echo_pos = -1;
36657
36658 DEFSYM (Qright_to_left, "right-to-left");
36659 DEFSYM (Qleft_to_right, "left-to-right");
36660 defsubr (&Sbidi_resolved_levels);
36661
36662 #ifdef HAVE_WINDOW_SYSTEM
36663 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36664 doc:
36665
36666 );
36667 x_stretch_cursor_p = 0;
36668 #endif
36669
36670 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36671 doc:
36672 );
36673 Vshow_trailing_whitespace = Qnil;
36674
36675 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36676 doc:
36677
36678
36679 );
36680 Vmode_line_compact = Qnil;
36681 DEFSYM (Qlong, "long");
36682
36683 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36684 doc:
36685
36686
36687
36688
36689
36690
36691
36692
36693
36694
36695
36696 );
36697 Vnobreak_char_display = Qt;
36698
36699 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
36700 doc:
36701
36702
36703
36704
36705
36706
36707
36708
36709
36710
36711
36712
36713
36714
36715
36716 );
36717 nobreak_char_ascii_display = false;
36718
36719 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
36720 doc:
36721
36722
36723 );
36724 Vvoid_text_area_pointer = Qarrow;
36725
36726 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
36727 doc:
36728 );
36729 Vinhibit_redisplay = Qnil;
36730
36731 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
36732 doc: );
36733 Vglobal_mode_string = Qnil;
36734
36735 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
36736 doc:
36737
36738 );
36739 Voverlay_arrow_position = Qnil;
36740
36741 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
36742 doc:
36743 );
36744 Voverlay_arrow_string = build_pure_c_string ("=>");
36745
36746 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
36747 doc:
36748
36749 );
36750 Voverlay_arrow_variable_list
36751 = list1 (intern_c_string ("overlay-arrow-position"));
36752
36753 DEFVAR_INT ("scroll-step", emacs_scroll_step,
36754 doc:
36755
36756
36757
36758 );
36759
36760 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
36761 doc:
36762
36763
36764
36765
36766
36767
36768
36769
36770
36771 );
36772 scroll_conservatively = 0;
36773
36774 DEFVAR_INT ("scroll-margin", scroll_margin,
36775 doc:
36776
36777 );
36778 scroll_margin = 0;
36779
36780 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
36781 doc:
36782
36783
36784
36785 );
36786 Vmaximum_scroll_margin = make_float (0.25);
36787
36788 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
36789 doc:
36790 );
36791 Vdisplay_pixels_per_inch = make_float (72.0);
36792
36793 #ifdef GLYPH_DEBUG
36794 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
36795 #endif
36796
36797 DEFVAR_LISP ("truncate-partial-width-windows",
36798 Vtruncate_partial_width_windows,
36799 doc:
36800
36801
36802
36803
36804
36805
36806
36807
36808
36809
36810
36811
36812
36813
36814
36815 );
36816 Vtruncate_partial_width_windows = make_fixnum (50);
36817
36818 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
36819
36820
36821
36822
36823
36824
36825
36826
36827
36828
36829
36830
36831
36832 );
36833 word_wrap_by_category = false;
36834
36835 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
36836 doc:
36837
36838 );
36839 Vline_number_display_limit = Qnil;
36840
36841 DEFVAR_INT ("line-number-display-limit-width",
36842 line_number_display_limit_width,
36843 doc:
36844
36845 );
36846 line_number_display_limit_width = 200;
36847
36848 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
36849 doc:
36850
36851 );
36852 highlight_nonselected_windows = false;
36853
36854 DEFVAR_BOOL ("multiple-frames", multiple_frames,
36855 doc:
36856
36857
36858 );
36859
36860 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
36861 doc:
36862
36863
36864
36865
36866 );
36867
36868 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
36869 doc:
36870
36871
36872
36873
36874
36875 );
36876
36877
36878 Lisp_Object icon_title_name_format
36879 = pure_list (empty_unibyte_string,
36880 build_pure_c_string ("%b - GNU Emacs at "),
36881 intern_c_string ("system-name"));
36882 Vicon_title_format
36883 = Vframe_title_format
36884 = pure_list (intern_c_string ("multiple-frames"),
36885 build_pure_c_string ("%b"),
36886 icon_title_name_format);
36887
36888 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
36889 doc:
36890
36891 );
36892 Vmessage_log_max = make_fixnum (1000);
36893
36894 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
36895 doc:
36896
36897
36898
36899
36900
36901
36902
36903
36904
36905
36906
36907
36908
36909 );
36910 Vwindow_scroll_functions = Qnil;
36911
36912 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
36913 doc:
36914
36915
36916
36917
36918
36919
36920
36921
36922
36923
36924
36925
36926
36927
36928
36929
36930
36931 );
36932 Vmouse_autoselect_window = Qnil;
36933
36934 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
36935 doc:
36936
36937
36938
36939
36940 );
36941 Vauto_resize_tab_bars = Qt;
36942
36943 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
36944 doc: );
36945 auto_raise_tab_bar_buttons_p = true;
36946
36947 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
36948 doc:
36949
36950
36951
36952
36953 );
36954 Vauto_resize_tool_bars = Qt;
36955
36956 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
36957 doc: );
36958 auto_raise_tool_bar_buttons_p = true;
36959
36960 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
36961 doc:
36962
36963
36964
36965
36966 );
36967 Vmake_cursor_line_fully_visible = Qt;
36968 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
36969
36970 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
36971 doc: );
36972 make_window_start_visible = false;
36973 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
36974 Fmake_variable_buffer_local (Qmake_window_start_visible);
36975
36976 DEFSYM (Qclose_tab, "close-tab");
36977 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
36978 doc:
36979
36980
36981
36982 );
36983 Vtab_bar_border = Qinternal_border_width;
36984
36985 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
36986 doc:
36987
36988
36989
36990 );
36991 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
36992
36993 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
36994 doc: );
36995 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
36996
36997 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
36998 doc:
36999
37000
37001
37002 );
37003 Vtool_bar_border = Qinternal_border_width;
37004
37005 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
37006 doc:
37007
37008
37009
37010 );
37011 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
37012
37013 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
37014 doc: );
37015 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
37016
37017 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
37018 doc:
37019
37020
37021
37022
37023
37024
37025
37026
37027 );
37028 Vtool_bar_style = Qnil;
37029
37030 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
37031 doc:
37032
37033 );
37034 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
37035
37036 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
37037 doc:
37038
37039
37040
37041
37042
37043
37044
37045
37046 );
37047 Vfontification_functions = Qnil;
37048 Fmake_variable_buffer_local (Qfontification_functions);
37049
37050 DEFVAR_BOOL ("unibyte-display-via-language-environment",
37051 unibyte_display_via_language_environment,
37052 doc:
37053
37054
37055
37056
37057
37058
37059 );
37060 unibyte_display_via_language_environment = false;
37061
37062 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
37063 doc:
37064
37065
37066
37067 );
37068 Vmax_mini_window_height = make_float (0.25);
37069
37070 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
37071 doc:
37072
37073
37074
37075
37076
37077
37078
37079
37080 );
37081
37082
37083
37084
37085
37086 Vresize_mini_windows = Qnil;
37087
37088 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
37089 doc:
37090
37091
37092
37093
37094
37095
37096
37097 );
37098 Vblink_cursor_alist = Qnil;
37099
37100 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
37101 doc:
37102
37103
37104
37105 );
37106 automatic_hscrolling = Qt;
37107 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
37108 DEFSYM (Qcurrent_line, "current-line");
37109
37110 DEFVAR_INT ("hscroll-margin", hscroll_margin,
37111 doc:
37112 );
37113 hscroll_margin = 5;
37114
37115 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37116 doc:
37117
37118
37119
37120
37121
37122
37123
37124
37125
37126
37127
37128
37129
37130 );
37131 Vhscroll_step = make_fixnum (0);
37132
37133 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37134 doc:
37135 );
37136 message_truncate_lines = false;
37137
37138 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37139 doc:
37140
37141
37142 );
37143 Vmenu_bar_update_hook = Qnil;
37144
37145 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37146 doc:
37147 );
37148 Vmenu_updating_frame = Qnil;
37149
37150 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37151 doc: );
37152 inhibit_menubar_update = false;
37153
37154 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37155 doc:
37156
37157
37158
37159
37160
37161
37162 );
37163 Vwrap_prefix = Qnil;
37164 DEFSYM (Qwrap_prefix, "wrap-prefix");
37165 Fmake_variable_buffer_local (Qwrap_prefix);
37166
37167 DEFVAR_LISP ("line-prefix", Vline_prefix,
37168 doc:
37169
37170
37171
37172
37173
37174
37175 );
37176 Vline_prefix = Qnil;
37177 DEFSYM (Qline_prefix, "line-prefix");
37178 Fmake_variable_buffer_local (Qline_prefix);
37179
37180 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37181 doc:
37182
37183
37184
37185
37186
37187
37188
37189
37190
37191
37192
37193
37194
37195
37196
37197
37198
37199
37200
37201
37202
37203
37204 );
37205 Vdisplay_line_numbers = Qnil;
37206 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37207 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37208 DEFSYM (Qrelative, "relative");
37209 DEFSYM (Qvisual, "visual");
37210
37211 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37212 doc:
37213
37214
37215
37216 );
37217 Vdisplay_line_numbers_width = Qnil;
37218 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37219 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37220
37221 DEFVAR_LISP ("display-line-numbers-current-absolute",
37222 Vdisplay_line_numbers_current_absolute,
37223 doc:
37224
37225 );
37226 Vdisplay_line_numbers_current_absolute = Qt;
37227
37228 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37229 doc: );
37230 display_line_numbers_widen = false;
37231 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37232 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37233
37234 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37235 doc:
37236
37237
37238 );
37239 display_line_numbers_offset = 0;
37240 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37241 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37242
37243 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37244 doc:
37245
37246
37247 );
37248 display_fill_column_indicator = false;
37249 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37250 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37251
37252 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37253 doc:
37254
37255
37256
37257 );
37258 Vdisplay_fill_column_indicator_column = Qt;
37259 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37260 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37261
37262 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37263 doc:
37264
37265
37266 );
37267 Vdisplay_fill_column_indicator_character = Qnil;
37268 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37269 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37270
37271 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37272 doc:
37273
37274
37275 );
37276 display_line_numbers_major_tick = 0;
37277
37278 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37279 doc:
37280
37281
37282 );
37283 display_line_numbers_minor_tick = 0;
37284
37285 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37286 doc: );
37287 inhibit_eval_during_redisplay = false;
37288
37289 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37290 doc: );
37291 inhibit_free_realized_faces = false;
37292
37293 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37294 doc:
37295
37296 );
37297 inhibit_bidi_mirroring = false;
37298
37299 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37300 doc:
37301
37302
37303
37304 );
37305 bidi_inhibit_bpa = false;
37306
37307 #ifdef GLYPH_DEBUG
37308 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37309 doc: );
37310 inhibit_try_window_id = false;
37311
37312 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37313 doc: );
37314 inhibit_try_window_reusing = false;
37315
37316 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37317 doc: );
37318 inhibit_try_cursor_movement = false;
37319 #endif
37320
37321 DEFVAR_INT ("overline-margin", overline_margin,
37322 doc:
37323
37324 );
37325 overline_margin = 2;
37326
37327 DEFVAR_INT ("underline-minimum-offset",
37328 underline_minimum_offset,
37329 doc:
37330
37331
37332
37333 );
37334 underline_minimum_offset = 1;
37335 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37336
37337 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37338 doc:
37339
37340 );
37341 display_hourglass_p = true;
37342
37343 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37344 doc: );
37345 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37346
37347 #ifdef HAVE_WINDOW_SYSTEM
37348 hourglass_atimer = NULL;
37349 hourglass_shown_p = false;
37350 #endif
37351
37352
37353 DEFSYM (Qglyphless_char, "glyphless-char");
37354
37355
37356 DEFSYM (Qhex_code, "hex-code");
37357 DEFSYM (Qempty_box, "empty-box");
37358 DEFSYM (Qthin_space, "thin-space");
37359 DEFSYM (Qzero_width, "zero-width");
37360
37361 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37362 doc:
37363
37364
37365 );
37366 Vpre_redisplay_function = intern ("ignore");
37367
37368
37369 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37370 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37371
37372 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37373 doc:
37374
37375
37376
37377
37378
37379
37380
37381
37382
37383
37384
37385
37386
37387
37388
37389
37390
37391
37392
37393
37394
37395
37396
37397 );
37398 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37399 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37400 Qempty_box);
37401
37402 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37403 doc: );
37404 Vdebug_on_message = Qnil;
37405
37406 DEFVAR_LISP ("set-message-function", Vset_message_function,
37407 doc:
37408
37409
37410
37411
37412
37413
37414
37415
37416
37417 );
37418 Vset_message_function = Qnil;
37419
37420 DEFSYM (Qdont_clear_message, "dont-clear-message");
37421 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37422 doc:
37423
37424
37425
37426
37427
37428
37429
37430
37431
37432
37433 );
37434 Vclear_message_function = Qnil;
37435
37436 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37437 doc:
37438 );
37439 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37440
37441 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37442 doc:
37443 );
37444 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37445
37446 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37447 doc: );
37448
37449
37450 redisplay__inhibit_bidi = true;
37451
37452 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37453 doc:
37454
37455 );
37456 display_raw_bytes_as_hex = false;
37457
37458 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37459 doc:
37460
37461 );
37462 mouse_fine_grained_tracking = false;
37463
37464 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37465 doc: );
37466 tab_bar__dragging_in_progress = false;
37467
37468 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37469 doc:
37470
37471
37472
37473 );
37474 redisplay_skip_initial_frame = true;
37475
37476 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37477 redisplay_skip_fontification_on_input,
37478 doc:
37479
37480
37481
37482
37483
37484
37485
37486 );
37487 redisplay_skip_fontification_on_input = false;
37488
37489 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37490 redisplay_adhoc_scroll_in_resize_mini_windows,
37491 doc:
37492
37493 );
37494
37495 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37496
37497 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37498 doc:
37499
37500 );
37501 composition_break_at_point = false;
37502
37503 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37504 doc:
37505
37506
37507
37508
37509
37510
37511
37512
37513
37514
37515
37516 );
37517 max_redisplay_ticks = 0;
37518 }
37519
37520
37521
37522
37523 void
37524 init_xdisp (void)
37525 {
37526 CHARPOS (this_line_start_pos) = 0;
37527
37528 echo_area_window = minibuf_window;
37529
37530 if (!noninteractive)
37531 {
37532 struct window *m = XWINDOW (minibuf_window);
37533 Lisp_Object frame = m->frame;
37534 struct frame *f = XFRAME (frame);
37535 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37536 struct window *r = XWINDOW (root);
37537 int i;
37538
37539 r->top_line = FRAME_TOP_MARGIN (f);
37540 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37541 r->total_cols = FRAME_COLS (f);
37542 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37543 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_MARGINS (f);
37544 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37545
37546 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37547 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37548 m->total_cols = FRAME_COLS (f);
37549 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37550 m->total_lines = 1;
37551 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37552
37553 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37554 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37555 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37556
37557
37558 for (i = 0; i < 3; ++i)
37559 default_invis_vector[i] = make_fixnum ('.');
37560 }
37561
37562 {
37563
37564
37565 int size = 100;
37566 mode_line_noprop_buf = xmalloc (size);
37567 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37568 mode_line_noprop_ptr = mode_line_noprop_buf;
37569 mode_line_target = MODE_LINE_DISPLAY;
37570 }
37571
37572 help_echo_showing_p = false;
37573 }
37574
37575 #ifdef HAVE_WINDOW_SYSTEM
37576
37577
37578
37579
37580
37581 static void
37582 show_hourglass (struct atimer *timer)
37583 {
37584
37585
37586
37587 hourglass_atimer = NULL;
37588
37589 if (!hourglass_shown_p)
37590 {
37591 Lisp_Object tail, frame;
37592
37593 block_input ();
37594
37595 FOR_EACH_FRAME (tail, frame)
37596 {
37597 struct frame *f = XFRAME (frame);
37598
37599 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37600 && FRAME_RIF (f)->show_hourglass)
37601 FRAME_RIF (f)->show_hourglass (f);
37602 }
37603
37604 hourglass_shown_p = true;
37605 unblock_input ();
37606 }
37607 }
37608
37609
37610
37611 void
37612 start_hourglass (void)
37613 {
37614 struct timespec delay;
37615
37616 cancel_hourglass ();
37617
37618 if (FIXNUMP (Vhourglass_delay)
37619 && XFIXNUM (Vhourglass_delay) > 0)
37620 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37621 TYPE_MAXIMUM (time_t)),
37622 0);
37623 else if (FLOATP (Vhourglass_delay)
37624 && XFLOAT_DATA (Vhourglass_delay) > 0)
37625 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37626 else
37627 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37628
37629 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37630 show_hourglass, NULL);
37631 }
37632
37633
37634
37635
37636 void
37637 cancel_hourglass (void)
37638 {
37639 if (hourglass_atimer)
37640 {
37641 cancel_atimer (hourglass_atimer);
37642 hourglass_atimer = NULL;
37643 }
37644
37645 if (hourglass_shown_p)
37646 {
37647 Lisp_Object tail, frame;
37648
37649 block_input ();
37650
37651 FOR_EACH_FRAME (tail, frame)
37652 {
37653 struct frame *f = XFRAME (frame);
37654
37655 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37656 && FRAME_RIF (f)->hide_hourglass)
37657 FRAME_RIF (f)->hide_hourglass (f);
37658 #ifdef HAVE_NTGUI
37659
37660 else if (!FRAME_W32_P (f))
37661 w32_arrow_cursor ();
37662 #endif
37663 }
37664
37665 hourglass_shown_p = false;
37666 unblock_input ();
37667 }
37668 }
37669
37670
37671
37672
37673
37674
37675
37676
37677 static int
37678 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37679 struct window *w,
37680 struct face *original_face,
37681 struct face *mouse_face)
37682 {
37683 int sum = 0;
37684
37685 bool do_left_box_p = g->left_box_line_p;
37686 bool do_right_box_p = g->right_box_line_p;
37687
37688
37689
37690 if (g->type == IMAGE_GLYPH)
37691 {
37692 if (!row->reversed_p)
37693 {
37694 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37695 g->u.img_id);
37696 do_left_box_p = g->left_box_line_p &&
37697 g->slice.img.x == 0;
37698 do_right_box_p = g->right_box_line_p &&
37699 g->slice.img.x + g->slice.img.width == img->width;
37700 }
37701 else
37702 {
37703 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37704 g->u.img_id);
37705 do_left_box_p = g->left_box_line_p &&
37706 g->slice.img.x + g->slice.img.width == img->width;
37707 do_right_box_p = g->right_box_line_p &&
37708 g->slice.img.x == 0;
37709 }
37710 }
37711
37712
37713 if (do_left_box_p)
37714 sum -= max (0, original_face->box_vertical_line_width);
37715
37716
37717 if (do_right_box_p)
37718 sum -= max (0, original_face->box_vertical_line_width);
37719
37720 if (g->left_box_line_p)
37721 sum += max (0, mouse_face->box_vertical_line_width);
37722 if (g->right_box_line_p)
37723 sum += max (0, mouse_face->box_vertical_line_width);
37724
37725 return sum;
37726 }
37727
37728
37729
37730
37731
37732
37733
37734
37735
37736 static void
37737 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
37738 int *offset)
37739 {
37740 int sum = 0;
37741
37742 if (row->mode_line_p)
37743 return;
37744
37745 block_input ();
37746
37747 struct frame *f = WINDOW_XFRAME (w);
37748 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
37749 struct glyph *start, *end;
37750 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
37751 int hpos = w->phys_cursor.hpos;
37752 end = &row->glyphs[TEXT_AREA][hpos];
37753
37754 if (!row->reversed_p)
37755 {
37756 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37757 hlinfo->mouse_face_beg_row)
37758 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
37759 else
37760 start = row->glyphs[TEXT_AREA];
37761 }
37762 else
37763 {
37764 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37765 hlinfo->mouse_face_end_row)
37766 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
37767 else
37768 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
37769 }
37770
37771
37772
37773
37774 for ( ; row->reversed_p ? start > end : start < end;
37775 row->reversed_p ? --start : ++start)
37776 sum += adjust_glyph_width_for_mouse_face (start, row, w,
37777 FACE_FROM_ID (f, start->face_id),
37778 mouse_face);
37779
37780 if (row->reversed_p)
37781 sum = -sum;
37782
37783 *offset = sum;
37784
37785 unblock_input ();
37786 }
37787 #endif